mechanize-store 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +8 -8
  2. data/README.rdoc +4 -2
  3. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/canvas-to-blob.min.js +1 -0
  4. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.blueimp-gallery.min.js +1 -0
  5. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-angular.js +429 -0
  6. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-audio.js +106 -0
  7. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-image.js +309 -0
  8. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-jquery-ui.js +152 -0
  9. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-process.js +172 -0
  10. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-ui.js +699 -0
  11. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-validate.js +119 -0
  12. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload-video.js +106 -0
  13. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.fileupload.js +1426 -0
  14. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.iframe-transport.js +214 -0
  15. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/jquery.ui.widget.js +530 -0
  16. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/load-image.min.js +1 -0
  17. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/main.js +14 -0
  18. data/app/assets/javascripts/mechanize_store/sb-admin/jquery-file-upload/tmpl.min.js +1 -0
  19. data/app/assets/stylesheets/mechanize_store/application.css +0 -2
  20. data/app/assets/stylesheets/mechanize_store/sb-admin/sb-admin.css +2 -2
  21. data/app/controllers/mechanize_store/product_photos_controller.rb +49 -0
  22. data/app/models/mechanize_store/product.rb +4 -3
  23. data/app/models/mechanize_store/product_photo.rb +11 -0
  24. data/app/views/layouts/{store → mechanize_store}/application.html.erb +38 -2
  25. data/app/views/mechanize_store/flags/_form.html.erb +1 -1
  26. data/app/views/mechanize_store/flags/index.html.erb +2 -2
  27. data/app/views/mechanize_store/order_statuses/_form.html.erb +6 -6
  28. data/app/views/mechanize_store/order_statuses/index.html.erb +3 -3
  29. data/app/views/mechanize_store/orders/index.html.erb +5 -5
  30. data/app/views/mechanize_store/payment_statuses/_form.html.erb +1 -1
  31. data/app/views/mechanize_store/payment_statuses/index.html.erb +3 -3
  32. data/app/views/mechanize_store/payment_types/_form.html.erb +6 -6
  33. data/app/views/mechanize_store/payment_types/index.html.erb +2 -2
  34. data/app/views/mechanize_store/product_categories/index.html.erb +4 -6
  35. data/app/views/mechanize_store/product_photos/create.json.jbuilder +9 -0
  36. data/app/views/mechanize_store/product_photos/index.json.jbuilder +9 -0
  37. data/app/views/mechanize_store/products/_form.html.erb +1 -1
  38. data/app/views/mechanize_store/products/index.html.erb +1 -1
  39. data/app/views/mechanize_store/products/show.html.erb +186 -32
  40. data/config/locales/store.pt-BR.yml +54 -11
  41. data/config/routes.rb +3 -2
  42. data/db/migrate/20140402153139_create_mechanize_store_orders.rb +1 -1
  43. data/lib/mechanize_store/version.rb +1 -1
  44. metadata +108 -7
  45. data/app/models/mechanize_store/store.rb +0 -5
  46. data/db/migrate/20140402141340_create_mechanize_store_stores.rb +0 -12
@@ -0,0 +1,172 @@
1
+ /*
2
+ * jQuery File Upload Processing Plugin 1.3.0
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2012, 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, 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
+ './jquery.fileupload'
22
+ ], factory);
23
+ } else {
24
+ // Browser globals:
25
+ factory(
26
+ window.jQuery
27
+ );
28
+ }
29
+ }(function ($) {
30
+ 'use strict';
31
+
32
+ var originalAdd = $.blueimp.fileupload.prototype.options.add;
33
+
34
+ // The File Upload Processing plugin extends the fileupload widget
35
+ // with file processing functionality:
36
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
37
+
38
+ options: {
39
+ // The list of processing actions:
40
+ processQueue: [
41
+ /*
42
+ {
43
+ action: 'log',
44
+ type: 'debug'
45
+ }
46
+ */
47
+ ],
48
+ add: function (e, data) {
49
+ var $this = $(this);
50
+ data.process(function () {
51
+ return $this.fileupload('process', data);
52
+ });
53
+ originalAdd.call(this, e, data);
54
+ }
55
+ },
56
+
57
+ processActions: {
58
+ /*
59
+ log: function (data, options) {
60
+ console[options.type](
61
+ 'Processing "' + data.files[data.index].name + '"'
62
+ );
63
+ }
64
+ */
65
+ },
66
+
67
+ _processFile: function (data, originalData) {
68
+ var that = this,
69
+ dfd = $.Deferred().resolveWith(that, [data]),
70
+ chain = dfd.promise();
71
+ this._trigger('process', null, data);
72
+ $.each(data.processQueue, function (i, settings) {
73
+ var func = function (data) {
74
+ if (originalData.errorThrown) {
75
+ return $.Deferred()
76
+ .rejectWith(that, [originalData]).promise();
77
+ }
78
+ return that.processActions[settings.action].call(
79
+ that,
80
+ data,
81
+ settings
82
+ );
83
+ };
84
+ chain = chain.pipe(func, settings.always && func);
85
+ });
86
+ chain
87
+ .done(function () {
88
+ that._trigger('processdone', null, data);
89
+ that._trigger('processalways', null, data);
90
+ })
91
+ .fail(function () {
92
+ that._trigger('processfail', null, data);
93
+ that._trigger('processalways', null, data);
94
+ });
95
+ return chain;
96
+ },
97
+
98
+ // Replaces the settings of each processQueue item that
99
+ // are strings starting with an "@", using the remaining
100
+ // substring as key for the option map,
101
+ // e.g. "@autoUpload" is replaced with options.autoUpload:
102
+ _transformProcessQueue: function (options) {
103
+ var processQueue = [];
104
+ $.each(options.processQueue, function () {
105
+ var settings = {},
106
+ action = this.action,
107
+ prefix = this.prefix === true ? action : this.prefix;
108
+ $.each(this, function (key, value) {
109
+ if ($.type(value) === 'string' &&
110
+ value.charAt(0) === '@') {
111
+ settings[key] = options[
112
+ value.slice(1) || (prefix ? prefix +
113
+ key.charAt(0).toUpperCase() + key.slice(1) : key)
114
+ ];
115
+ } else {
116
+ settings[key] = value;
117
+ }
118
+
119
+ });
120
+ processQueue.push(settings);
121
+ });
122
+ options.processQueue = processQueue;
123
+ },
124
+
125
+ // Returns the number of files currently in the processsing queue:
126
+ processing: function () {
127
+ return this._processing;
128
+ },
129
+
130
+ // Processes the files given as files property of the data parameter,
131
+ // returns a Promise object that allows to bind callbacks:
132
+ process: function (data) {
133
+ var that = this,
134
+ options = $.extend({}, this.options, data);
135
+ if (options.processQueue && options.processQueue.length) {
136
+ this._transformProcessQueue(options);
137
+ if (this._processing === 0) {
138
+ this._trigger('processstart');
139
+ }
140
+ $.each(data.files, function (index) {
141
+ var opts = index ? $.extend({}, options) : options,
142
+ func = function () {
143
+ if (data.errorThrown) {
144
+ return $.Deferred()
145
+ .rejectWith(that, [data]).promise();
146
+ }
147
+ return that._processFile(opts, data);
148
+ };
149
+ opts.index = index;
150
+ that._processing += 1;
151
+ that._processingQueue = that._processingQueue.pipe(func, func)
152
+ .always(function () {
153
+ that._processing -= 1;
154
+ if (that._processing === 0) {
155
+ that._trigger('processstop');
156
+ }
157
+ });
158
+ });
159
+ }
160
+ return this._processingQueue;
161
+ },
162
+
163
+ _create: function () {
164
+ this._super();
165
+ this._processing = 0;
166
+ this._processingQueue = $.Deferred().resolveWith(this)
167
+ .promise();
168
+ }
169
+
170
+ });
171
+
172
+ }));
@@ -0,0 +1,699 @@
1
+ /*
2
+ * jQuery File Upload User Interface Plugin 9.5.2
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2010, 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, 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
+ 'tmpl',
22
+ './jquery.fileupload-image',
23
+ './jquery.fileupload-audio',
24
+ './jquery.fileupload-video',
25
+ './jquery.fileupload-validate'
26
+ ], factory);
27
+ } else {
28
+ // Browser globals:
29
+ factory(
30
+ window.jQuery,
31
+ window.tmpl
32
+ );
33
+ }
34
+ }(function ($, tmpl) {
35
+ 'use strict';
36
+
37
+ $.blueimp.fileupload.prototype._specialOptions.push(
38
+ 'filesContainer',
39
+ 'uploadTemplateId',
40
+ 'downloadTemplateId'
41
+ );
42
+
43
+ // The UI version extends the file upload widget
44
+ // and adds complete user interface interaction:
45
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
46
+
47
+ options: {
48
+ // By default, files added to the widget are uploaded as soon
49
+ // as the user clicks on the start buttons. To enable automatic
50
+ // uploads, set the following option to true:
51
+ autoUpload: false,
52
+ // The ID of the upload template:
53
+ uploadTemplateId: 'template-upload',
54
+ // The ID of the download template:
55
+ downloadTemplateId: 'template-download',
56
+ // The container for the list of files. If undefined, it is set to
57
+ // an element with class "files" inside of the widget element:
58
+ filesContainer: undefined,
59
+ // By default, files are appended to the files container.
60
+ // Set the following option to true, to prepend files instead:
61
+ prependFiles: false,
62
+ // The expected data type of the upload response, sets the dataType
63
+ // option of the $.ajax upload requests:
64
+ dataType: 'json',
65
+
66
+ // Function returning the current number of files,
67
+ // used by the maxNumberOfFiles validation:
68
+ getNumberOfFiles: function () {
69
+ return this.filesContainer.children()
70
+ .not('.processing').length;
71
+ },
72
+
73
+ // Callback to retrieve the list of files from the server response:
74
+ getFilesFromResponse: function (data) {
75
+ if (data.result && $.isArray(data.result.files)) {
76
+ return data.result.files;
77
+ }
78
+ return [];
79
+ },
80
+
81
+ // The add callback is invoked as soon as files are added to the fileupload
82
+ // widget (via file input selection, drag & drop or add API call).
83
+ // See the basic file upload widget for more information:
84
+ add: function (e, data) {
85
+ if (e.isDefaultPrevented()) {
86
+ return false;
87
+ }
88
+ var $this = $(this),
89
+ that = $this.data('blueimp-fileupload') ||
90
+ $this.data('fileupload'),
91
+ options = that.options;
92
+ data.context = that._renderUpload(data.files)
93
+ .data('data', data)
94
+ .addClass('processing');
95
+ options.filesContainer[
96
+ options.prependFiles ? 'prepend' : 'append'
97
+ ](data.context);
98
+ that._forceReflow(data.context);
99
+ that._transition(data.context);
100
+ data.process(function () {
101
+ return $this.fileupload('process', data);
102
+ }).always(function () {
103
+ data.context.each(function (index) {
104
+ $(this).find('.size').text(
105
+ that._formatFileSize(data.files[index].size)
106
+ );
107
+ }).removeClass('processing');
108
+ that._renderPreviews(data);
109
+ }).done(function () {
110
+ data.context.find('.start').prop('disabled', false);
111
+ if ((that._trigger('added', e, data) !== false) &&
112
+ (options.autoUpload || data.autoUpload) &&
113
+ data.autoUpload !== false) {
114
+ data.submit();
115
+ }
116
+ }).fail(function () {
117
+ if (data.files.error) {
118
+ data.context.each(function (index) {
119
+ var error = data.files[index].error;
120
+ if (error) {
121
+ $(this).find('.error').text(error);
122
+ }
123
+ });
124
+ }
125
+ });
126
+ },
127
+ // Callback for the start of each file upload request:
128
+ send: function (e, data) {
129
+ if (e.isDefaultPrevented()) {
130
+ return false;
131
+ }
132
+ var that = $(this).data('blueimp-fileupload') ||
133
+ $(this).data('fileupload');
134
+ if (data.context && data.dataType &&
135
+ data.dataType.substr(0, 6) === 'iframe') {
136
+ // Iframe Transport does not support progress events.
137
+ // In lack of an indeterminate progress bar, we set
138
+ // the progress to 100%, showing the full animated bar:
139
+ data.context
140
+ .find('.progress').addClass(
141
+ !$.support.transition && 'progress-animated'
142
+ )
143
+ .attr('aria-valuenow', 100)
144
+ .children().first().css(
145
+ 'width',
146
+ '100%'
147
+ );
148
+ }
149
+ return that._trigger('sent', e, data);
150
+ },
151
+ // Callback for successful uploads:
152
+ done: function (e, data) {
153
+ if (e.isDefaultPrevented()) {
154
+ return false;
155
+ }
156
+ var that = $(this).data('blueimp-fileupload') ||
157
+ $(this).data('fileupload'),
158
+ getFilesFromResponse = data.getFilesFromResponse ||
159
+ that.options.getFilesFromResponse,
160
+ files = getFilesFromResponse(data),
161
+ template,
162
+ deferred;
163
+ if (data.context) {
164
+ data.context.each(function (index) {
165
+ var file = files[index] ||
166
+ {error: 'Empty file upload result'};
167
+ deferred = that._addFinishedDeferreds();
168
+ that._transition($(this)).done(
169
+ function () {
170
+ var node = $(this);
171
+ template = that._renderDownload([file])
172
+ .replaceAll(node);
173
+ that._forceReflow(template);
174
+ that._transition(template).done(
175
+ function () {
176
+ data.context = $(this);
177
+ that._trigger('completed', e, data);
178
+ that._trigger('finished', e, data);
179
+ deferred.resolve();
180
+ }
181
+ );
182
+ }
183
+ );
184
+ });
185
+ } else {
186
+ template = that._renderDownload(files)[
187
+ that.options.prependFiles ? 'prependTo' : 'appendTo'
188
+ ](that.options.filesContainer);
189
+ that._forceReflow(template);
190
+ deferred = that._addFinishedDeferreds();
191
+ that._transition(template).done(
192
+ function () {
193
+ data.context = $(this);
194
+ that._trigger('completed', e, data);
195
+ that._trigger('finished', e, data);
196
+ deferred.resolve();
197
+ }
198
+ );
199
+ }
200
+ },
201
+ // Callback for failed (abort or error) uploads:
202
+ fail: function (e, data) {
203
+ if (e.isDefaultPrevented()) {
204
+ return false;
205
+ }
206
+ var that = $(this).data('blueimp-fileupload') ||
207
+ $(this).data('fileupload'),
208
+ template,
209
+ deferred;
210
+ if (data.context) {
211
+ data.context.each(function (index) {
212
+ if (data.errorThrown !== 'abort') {
213
+ var file = data.files[index];
214
+ file.error = file.error || data.errorThrown ||
215
+ true;
216
+ deferred = that._addFinishedDeferreds();
217
+ that._transition($(this)).done(
218
+ function () {
219
+ var node = $(this);
220
+ template = that._renderDownload([file])
221
+ .replaceAll(node);
222
+ that._forceReflow(template);
223
+ that._transition(template).done(
224
+ function () {
225
+ data.context = $(this);
226
+ that._trigger('failed', e, data);
227
+ that._trigger('finished', e, data);
228
+ deferred.resolve();
229
+ }
230
+ );
231
+ }
232
+ );
233
+ } else {
234
+ deferred = that._addFinishedDeferreds();
235
+ that._transition($(this)).done(
236
+ function () {
237
+ $(this).remove();
238
+ that._trigger('failed', e, data);
239
+ that._trigger('finished', e, data);
240
+ deferred.resolve();
241
+ }
242
+ );
243
+ }
244
+ });
245
+ } else if (data.errorThrown !== 'abort') {
246
+ data.context = that._renderUpload(data.files)[
247
+ that.options.prependFiles ? 'prependTo' : 'appendTo'
248
+ ](that.options.filesContainer)
249
+ .data('data', data);
250
+ that._forceReflow(data.context);
251
+ deferred = that._addFinishedDeferreds();
252
+ that._transition(data.context).done(
253
+ function () {
254
+ data.context = $(this);
255
+ that._trigger('failed', e, data);
256
+ that._trigger('finished', e, data);
257
+ deferred.resolve();
258
+ }
259
+ );
260
+ } else {
261
+ that._trigger('failed', e, data);
262
+ that._trigger('finished', e, data);
263
+ that._addFinishedDeferreds().resolve();
264
+ }
265
+ },
266
+ // Callback for upload progress events:
267
+ progress: function (e, data) {
268
+ if (e.isDefaultPrevented()) {
269
+ return false;
270
+ }
271
+ var progress = Math.floor(data.loaded / data.total * 100);
272
+ if (data.context) {
273
+ data.context.each(function () {
274
+ $(this).find('.progress')
275
+ .attr('aria-valuenow', progress)
276
+ .children().first().css(
277
+ 'width',
278
+ progress + '%'
279
+ );
280
+ });
281
+ }
282
+ },
283
+ // Callback for global upload progress events:
284
+ progressall: function (e, data) {
285
+ if (e.isDefaultPrevented()) {
286
+ return false;
287
+ }
288
+ var $this = $(this),
289
+ progress = Math.floor(data.loaded / data.total * 100),
290
+ globalProgressNode = $this.find('.fileupload-progress'),
291
+ extendedProgressNode = globalProgressNode
292
+ .find('.progress-extended');
293
+ if (extendedProgressNode.length) {
294
+ extendedProgressNode.html(
295
+ ($this.data('blueimp-fileupload') || $this.data('fileupload'))
296
+ ._renderExtendedProgress(data)
297
+ );
298
+ }
299
+ globalProgressNode
300
+ .find('.progress')
301
+ .attr('aria-valuenow', progress)
302
+ .children().first().css(
303
+ 'width',
304
+ progress + '%'
305
+ );
306
+ },
307
+ // Callback for uploads start, equivalent to the global ajaxStart event:
308
+ start: function (e) {
309
+ if (e.isDefaultPrevented()) {
310
+ return false;
311
+ }
312
+ var that = $(this).data('blueimp-fileupload') ||
313
+ $(this).data('fileupload');
314
+ that._resetFinishedDeferreds();
315
+ that._transition($(this).find('.fileupload-progress')).done(
316
+ function () {
317
+ that._trigger('started', e);
318
+ }
319
+ );
320
+ },
321
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
322
+ stop: function (e) {
323
+ if (e.isDefaultPrevented()) {
324
+ return false;
325
+ }
326
+ var that = $(this).data('blueimp-fileupload') ||
327
+ $(this).data('fileupload'),
328
+ deferred = that._addFinishedDeferreds();
329
+ $.when.apply($, that._getFinishedDeferreds())
330
+ .done(function () {
331
+ that._trigger('stopped', e);
332
+ });
333
+ that._transition($(this).find('.fileupload-progress')).done(
334
+ function () {
335
+ $(this).find('.progress')
336
+ .attr('aria-valuenow', '0')
337
+ .children().first().css('width', '0%');
338
+ $(this).find('.progress-extended').html(' ');
339
+ deferred.resolve();
340
+ }
341
+ );
342
+ },
343
+ processstart: function (e) {
344
+ if (e.isDefaultPrevented()) {
345
+ return false;
346
+ }
347
+ $(this).addClass('fileupload-processing');
348
+ },
349
+ processstop: function (e) {
350
+ if (e.isDefaultPrevented()) {
351
+ return false;
352
+ }
353
+ $(this).removeClass('fileupload-processing');
354
+ },
355
+ // Callback for file deletion:
356
+ destroy: function (e, data) {
357
+ if (e.isDefaultPrevented()) {
358
+ return false;
359
+ }
360
+ var that = $(this).data('blueimp-fileupload') ||
361
+ $(this).data('fileupload'),
362
+ removeNode = function () {
363
+ that._transition(data.context).done(
364
+ function () {
365
+ $(this).remove();
366
+ that._trigger('destroyed', e, data);
367
+ }
368
+ );
369
+ };
370
+ if (data.url) {
371
+ data.dataType = data.dataType || that.options.dataType;
372
+ $.ajax(data).done(removeNode).fail(function () {
373
+ that._trigger('destroyfailed', e, data);
374
+ });
375
+ } else {
376
+ removeNode();
377
+ }
378
+ }
379
+ },
380
+
381
+ _resetFinishedDeferreds: function () {
382
+ this._finishedUploads = [];
383
+ },
384
+
385
+ _addFinishedDeferreds: function (deferred) {
386
+ if (!deferred) {
387
+ deferred = $.Deferred();
388
+ }
389
+ this._finishedUploads.push(deferred);
390
+ return deferred;
391
+ },
392
+
393
+ _getFinishedDeferreds: function () {
394
+ return this._finishedUploads;
395
+ },
396
+
397
+ // Link handler, that allows to download files
398
+ // by drag & drop of the links to the desktop:
399
+ _enableDragToDesktop: function () {
400
+ var link = $(this),
401
+ url = link.prop('href'),
402
+ name = link.prop('download'),
403
+ type = 'application/octet-stream';
404
+ link.bind('dragstart', function (e) {
405
+ try {
406
+ e.originalEvent.dataTransfer.setData(
407
+ 'DownloadURL',
408
+ [type, name, url].join(':')
409
+ );
410
+ } catch (ignore) {}
411
+ });
412
+ },
413
+
414
+ _formatFileSize: function (bytes) {
415
+ if (typeof bytes !== 'number') {
416
+ return '';
417
+ }
418
+ if (bytes >= 1000000000) {
419
+ return (bytes / 1000000000).toFixed(2) + ' GB';
420
+ }
421
+ if (bytes >= 1000000) {
422
+ return (bytes / 1000000).toFixed(2) + ' MB';
423
+ }
424
+ return (bytes / 1000).toFixed(2) + ' KB';
425
+ },
426
+
427
+ _formatBitrate: function (bits) {
428
+ if (typeof bits !== 'number') {
429
+ return '';
430
+ }
431
+ if (bits >= 1000000000) {
432
+ return (bits / 1000000000).toFixed(2) + ' Gbit/s';
433
+ }
434
+ if (bits >= 1000000) {
435
+ return (bits / 1000000).toFixed(2) + ' Mbit/s';
436
+ }
437
+ if (bits >= 1000) {
438
+ return (bits / 1000).toFixed(2) + ' kbit/s';
439
+ }
440
+ return bits.toFixed(2) + ' bit/s';
441
+ },
442
+
443
+ _formatTime: function (seconds) {
444
+ var date = new Date(seconds * 1000),
445
+ days = Math.floor(seconds / 86400);
446
+ days = days ? days + 'd ' : '';
447
+ return days +
448
+ ('0' + date.getUTCHours()).slice(-2) + ':' +
449
+ ('0' + date.getUTCMinutes()).slice(-2) + ':' +
450
+ ('0' + date.getUTCSeconds()).slice(-2);
451
+ },
452
+
453
+ _formatPercentage: function (floatValue) {
454
+ return (floatValue * 100).toFixed(2) + ' %';
455
+ },
456
+
457
+ _renderExtendedProgress: function (data) {
458
+ return this._formatBitrate(data.bitrate) + ' | ' +
459
+ this._formatTime(
460
+ (data.total - data.loaded) * 8 / data.bitrate
461
+ ) + ' | ' +
462
+ this._formatPercentage(
463
+ data.loaded / data.total
464
+ ) + ' | ' +
465
+ this._formatFileSize(data.loaded) + ' / ' +
466
+ this._formatFileSize(data.total);
467
+ },
468
+
469
+ _renderTemplate: function (func, files) {
470
+ if (!func) {
471
+ return $();
472
+ }
473
+ var result = func({
474
+ files: files,
475
+ formatFileSize: this._formatFileSize,
476
+ options: this.options
477
+ });
478
+ if (result instanceof $) {
479
+ return result;
480
+ }
481
+ return $(this.options.templatesContainer).html(result).children();
482
+ },
483
+
484
+ _renderPreviews: function (data) {
485
+ data.context.find('.preview').each(function (index, elm) {
486
+ $(elm).append(data.files[index].preview);
487
+ });
488
+ },
489
+
490
+ _renderUpload: function (files) {
491
+ return this._renderTemplate(
492
+ this.options.uploadTemplate,
493
+ files
494
+ );
495
+ },
496
+
497
+ _renderDownload: function (files) {
498
+ return this._renderTemplate(
499
+ this.options.downloadTemplate,
500
+ files
501
+ ).find('a[download]').each(this._enableDragToDesktop).end();
502
+ },
503
+
504
+ _startHandler: function (e) {
505
+ e.preventDefault();
506
+ var button = $(e.currentTarget),
507
+ template = button.closest('.template-upload'),
508
+ data = template.data('data');
509
+ button.prop('disabled', true);
510
+ if (data && data.submit) {
511
+ data.submit();
512
+ }
513
+ },
514
+
515
+ _cancelHandler: function (e) {
516
+ e.preventDefault();
517
+ var template = $(e.currentTarget)
518
+ .closest('.template-upload,.template-download'),
519
+ data = template.data('data') || {};
520
+ data.context = data.context || template;
521
+ if (data.abort) {
522
+ data.abort();
523
+ } else {
524
+ data.errorThrown = 'abort';
525
+ this._trigger('fail', e, data);
526
+ }
527
+ },
528
+
529
+ _deleteHandler: function (e) {
530
+ e.preventDefault();
531
+ var button = $(e.currentTarget);
532
+ this._trigger('destroy', e, $.extend({
533
+ context: button.closest('.template-download'),
534
+ type: 'DELETE'
535
+ }, button.data()));
536
+ },
537
+
538
+ _forceReflow: function (node) {
539
+ return $.support.transition && node.length &&
540
+ node[0].offsetWidth;
541
+ },
542
+
543
+ _transition: function (node) {
544
+ var dfd = $.Deferred();
545
+ if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
546
+ node.bind(
547
+ $.support.transition.end,
548
+ function (e) {
549
+ // Make sure we don't respond to other transitions events
550
+ // in the container element, e.g. from button elements:
551
+ if (e.target === node[0]) {
552
+ node.unbind($.support.transition.end);
553
+ dfd.resolveWith(node);
554
+ }
555
+ }
556
+ ).toggleClass('in');
557
+ } else {
558
+ node.toggleClass('in');
559
+ dfd.resolveWith(node);
560
+ }
561
+ return dfd;
562
+ },
563
+
564
+ _initButtonBarEventHandlers: function () {
565
+ var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
566
+ filesList = this.options.filesContainer;
567
+ this._on(fileUploadButtonBar.find('.start'), {
568
+ click: function (e) {
569
+ e.preventDefault();
570
+ filesList.find('.start').click();
571
+ }
572
+ });
573
+ this._on(fileUploadButtonBar.find('.cancel'), {
574
+ click: function (e) {
575
+ e.preventDefault();
576
+ filesList.find('.cancel').click();
577
+ }
578
+ });
579
+ this._on(fileUploadButtonBar.find('.delete'), {
580
+ click: function (e) {
581
+ e.preventDefault();
582
+ filesList.find('.toggle:checked')
583
+ .closest('.template-download')
584
+ .find('.delete').click();
585
+ fileUploadButtonBar.find('.toggle')
586
+ .prop('checked', false);
587
+ }
588
+ });
589
+ this._on(fileUploadButtonBar.find('.toggle'), {
590
+ change: function (e) {
591
+ filesList.find('.toggle').prop(
592
+ 'checked',
593
+ $(e.currentTarget).is(':checked')
594
+ );
595
+ }
596
+ });
597
+ },
598
+
599
+ _destroyButtonBarEventHandlers: function () {
600
+ this._off(
601
+ this.element.find('.fileupload-buttonbar')
602
+ .find('.start, .cancel, .delete'),
603
+ 'click'
604
+ );
605
+ this._off(
606
+ this.element.find('.fileupload-buttonbar .toggle'),
607
+ 'change.'
608
+ );
609
+ },
610
+
611
+ _initEventHandlers: function () {
612
+ this._super();
613
+ this._on(this.options.filesContainer, {
614
+ 'click .start': this._startHandler,
615
+ 'click .cancel': this._cancelHandler,
616
+ 'click .delete': this._deleteHandler
617
+ });
618
+ this._initButtonBarEventHandlers();
619
+ },
620
+
621
+ _destroyEventHandlers: function () {
622
+ this._destroyButtonBarEventHandlers();
623
+ this._off(this.options.filesContainer, 'click');
624
+ this._super();
625
+ },
626
+
627
+ _enableFileInputButton: function () {
628
+ this.element.find('.fileinput-button input')
629
+ .prop('disabled', false)
630
+ .parent().removeClass('disabled');
631
+ },
632
+
633
+ _disableFileInputButton: function () {
634
+ this.element.find('.fileinput-button input')
635
+ .prop('disabled', true)
636
+ .parent().addClass('disabled');
637
+ },
638
+
639
+ _initTemplates: function () {
640
+ var options = this.options;
641
+ options.templatesContainer = this.document[0].createElement(
642
+ options.filesContainer.prop('nodeName')
643
+ );
644
+ if (tmpl) {
645
+ if (options.uploadTemplateId) {
646
+ options.uploadTemplate = tmpl(options.uploadTemplateId);
647
+ }
648
+ if (options.downloadTemplateId) {
649
+ options.downloadTemplate = tmpl(options.downloadTemplateId);
650
+ }
651
+ }
652
+ },
653
+
654
+ _initFilesContainer: function () {
655
+ var options = this.options;
656
+ if (options.filesContainer === undefined) {
657
+ options.filesContainer = this.element.find('.files');
658
+ } else if (!(options.filesContainer instanceof $)) {
659
+ options.filesContainer = $(options.filesContainer);
660
+ }
661
+ },
662
+
663
+ _initSpecialOptions: function () {
664
+ this._super();
665
+ this._initFilesContainer();
666
+ this._initTemplates();
667
+ },
668
+
669
+ _create: function () {
670
+ this._super();
671
+ this._resetFinishedDeferreds();
672
+ if (!$.support.fileInput) {
673
+ this._disableFileInputButton();
674
+ }
675
+ },
676
+
677
+ enable: function () {
678
+ var wasDisabled = false;
679
+ if (this.options.disabled) {
680
+ wasDisabled = true;
681
+ }
682
+ this._super();
683
+ if (wasDisabled) {
684
+ this.element.find('input, button').prop('disabled', false);
685
+ this._enableFileInputButton();
686
+ }
687
+ },
688
+
689
+ disable: function () {
690
+ if (!this.options.disabled) {
691
+ this.element.find('input, button').prop('disabled', true);
692
+ this._disableFileInputButton();
693
+ }
694
+ this._super();
695
+ }
696
+
697
+ });
698
+
699
+ }));