glebtv-rails-uploader 0.4.1 → 0.5.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -146
  3. data/Rakefile +2 -2
  4. data/app/assets/javascripts/uploader/application.js +5 -6
  5. data/app/assets/javascripts/uploader/rails_admin.js +6 -25
  6. data/app/assets/stylesheets/uploader/application.css.sass +2 -0
  7. data/app/assets/stylesheets/uploader/{application.css → application.css.scss} +0 -0
  8. data/app/controllers/uploader/attachments_controller.rb +28 -50
  9. data/app/views/rails_admin/main/_form_rails_uploader.haml +1 -10
  10. data/app/views/uploader/default/_container.html.erb +49 -64
  11. data/app/views/uploader/default/_download.html.erb +16 -12
  12. data/app/views/uploader/default/_upload.html.erb +2 -2
  13. data/config/routes.rb +1 -5
  14. data/lib/glebtv-rails-uploader.rb +0 -1
  15. data/lib/uploader.rb +5 -5
  16. data/lib/uploader/asset.rb +84 -41
  17. data/lib/uploader/engine.rb +10 -6
  18. data/lib/uploader/fileuploads.rb +53 -31
  19. data/lib/uploader/helpers/field_tag.rb +24 -35
  20. data/lib/uploader/helpers/form_builder.rb +1 -1
  21. data/lib/uploader/helpers/form_tag_helper.rb +2 -3
  22. data/lib/uploader/hooks/formtastic.rb +10 -4
  23. data/lib/uploader/hooks/simple_form.rb +1 -3
  24. data/lib/uploader/version.rb +1 -1
  25. data/spec/dummy/app/models/article.rb +3 -7
  26. data/spec/dummy/app/models/asset.rb +26 -19
  27. data/spec/dummy/app/models/picture.rb +4 -4
  28. data/spec/dummy/config/application.rb +5 -7
  29. data/spec/dummy/config/environments/development.rb +1 -5
  30. data/spec/dummy/config/environments/production.rb +0 -4
  31. data/spec/dummy/config/environments/test.rb +2 -6
  32. data/spec/dummy/db/migrate/20120508093416_create_assets.rb +3 -1
  33. data/spec/factories/articles.rb +1 -0
  34. data/spec/factories/assets.rb +1 -0
  35. data/spec/fileuploads_spec.rb +2 -2
  36. data/spec/mongoid_spec.rb +4 -6
  37. data/spec/requests/attachments_controller_spec.rb +10 -2
  38. data/spec/spec_helper.rb +7 -3
  39. data/spec/uploader_spec.rb +1 -1
  40. data/{app → vendor}/assets/images/uploader/but_del_tag2.png +0 -0
  41. data/{app → vendor}/assets/images/uploader/ico_attach.png +0 -0
  42. data/{app → vendor}/assets/images/uploader/preloader.gif +0 -0
  43. data/{app → vendor}/assets/images/uploader/progressBarFillBg.png +0 -0
  44. data/vendor/assets/javascripts/uploader/jquery.fileupload-fp.js +8 -4
  45. data/{app → vendor}/assets/javascripts/uploader/jquery.fileupload-ui.js +219 -44
  46. data/{app → vendor}/assets/javascripts/uploader/jquery.fileupload.js +16 -74
  47. data/{app → vendor}/assets/javascripts/uploader/jquery.iframe-transport.js +3 -9
  48. data/vendor/assets/javascripts/uploader/load-image.min.js +1 -0
  49. data/{app → vendor}/assets/javascripts/uploader/locales/en.js +0 -0
  50. data/{app → vendor}/assets/javascripts/uploader/locales/ru.js +0 -0
  51. data/{app → vendor}/assets/javascripts/uploader/locales/uk.js +0 -0
  52. data/vendor/assets/javascripts/uploader/tmpl.min.js +1 -0
  53. data/{app/assets/stylesheets/uploader/default.css → vendor/assets/stylesheets/uploader/default.css.scss} +3 -11
  54. data/{app/assets/stylesheets/uploader/jquery.fileupload-ui.css → vendor/assets/stylesheets/uploader/jquery.fileupload-ui.css.scss} +0 -0
  55. metadata +78 -146
  56. data/app/assets/javascripts/uploader/canvas-to-blob.js +0 -95
  57. data/app/assets/javascripts/uploader/jquery.fileupload-angular.js +0 -348
  58. data/app/assets/javascripts/uploader/jquery.fileupload-process.js +0 -158
  59. data/app/assets/javascripts/uploader/jquery.fileupload-resize.js +0 -212
  60. data/app/assets/javascripts/uploader/jquery.fileupload-validate.js +0 -116
  61. data/app/assets/javascripts/uploader/jquery.ui.widget.js +0 -530
  62. data/app/assets/javascripts/uploader/load-image.js +0 -381
  63. data/app/assets/javascripts/uploader/tmpl.js +0 -86
  64. data/lib/file_size_validator.rb +0 -68
  65. data/spec/dummy/config/mongoid.yml +0 -12
@@ -8,7 +8,7 @@ describe Uploader do
8
8
  it "should generate random string" do
9
9
  value = Uploader.guid
10
10
  value.should_not be_blank
11
- value.size.should == 10
11
+ value.size.should == 20
12
12
  end
13
13
 
14
14
  it "should find all precompile assets" do
@@ -1,5 +1,5 @@
1
1
  /*
2
- * jQuery File Upload File Processing Plugin 1.2.1
2
+ * jQuery File Upload File Processing Plugin 1.2.3
3
3
  * https://github.com/blueimp/jQuery-File-Upload
4
4
  *
5
5
  * Copyright 2012, Sebastian Tschan
@@ -62,9 +62,13 @@
62
62
  // fileupload widget (via file input selection, drag & drop or add
63
63
  // API call). See the basic file upload widget for more information:
64
64
  add: function (e, data) {
65
- $(this).fileupload('process', data).done(function () {
66
- data.submit();
67
- });
65
+ if (data.autoUpload || (data.autoUpload !== false &&
66
+ ($(this).data('blueimp-fileupload') ||
67
+ $(this).data('fileupload')).options.autoUpload)) {
68
+ $(this).fileupload('process', data).done(function () {
69
+ data.submit();
70
+ });
71
+ }
68
72
  }
69
73
  },
70
74
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * jQuery File Upload User Interface Plugin 8.2.1
2
+ * jQuery File Upload User Interface Plugin 7.4.4
3
3
  * https://github.com/blueimp/jQuery-File-Upload
4
4
  *
5
5
  * Copyright 2010, Sebastian Tschan
@@ -19,25 +19,20 @@
19
19
  define([
20
20
  'jquery',
21
21
  'tmpl',
22
- './jquery.fileupload-resize',
23
- './jquery.fileupload-validate'
22
+ 'load-image',
23
+ './jquery.fileupload-fp'
24
24
  ], factory);
25
25
  } else {
26
26
  // Browser globals:
27
27
  factory(
28
28
  window.jQuery,
29
- window.tmpl
29
+ window.tmpl,
30
+ window.loadImage
30
31
  );
31
32
  }
32
33
  }(function ($, tmpl, loadImage) {
33
34
  'use strict';
34
35
 
35
- $.blueimp.fileupload.prototype._specialOptions.push(
36
- 'filesContainer',
37
- 'uploadTemplateId',
38
- 'downloadTemplateId'
39
- );
40
-
41
36
  // The UI version extends the file upload widget
42
37
  // and adds complete user interface interaction:
43
38
  $.widget('blueimp.fileupload', $.blueimp.fileupload, {
@@ -47,6 +42,29 @@
47
42
  // as the user clicks on the start buttons. To enable automatic
48
43
  // uploads, set the following option to true:
49
44
  autoUpload: false,
45
+ // The following option limits the number of files that are
46
+ // allowed to be uploaded using this widget:
47
+ maxNumberOfFiles: undefined,
48
+ // The maximum allowed file size:
49
+ maxFileSize: undefined,
50
+ // The minimum allowed file size:
51
+ minFileSize: undefined,
52
+ // The regular expression for allowed file types, matches
53
+ // against either file type or file name:
54
+ acceptFileTypes: /.+$/i,
55
+ // The regular expression to define for which files a preview
56
+ // image is shown, matched against the file type:
57
+ previewSourceFileTypes: /^image\/(gif|jpeg|png)$/,
58
+ // The maximum file size of images that are to be displayed as preview:
59
+ previewSourceMaxFileSize: 5000000, // 5MB
60
+ // The maximum width of the preview images:
61
+ previewMaxWidth: 80,
62
+ // The maximum height of the preview images:
63
+ previewMaxHeight: 80,
64
+ // By default, preview images are displayed as canvas elements
65
+ // if supported by the browser. Set the following option to false
66
+ // to always display preview images as img elements:
67
+ previewAsCanvas: true,
50
68
  // The ID of the upload template:
51
69
  uploadTemplateId: 'template-upload',
52
70
  // The ID of the download template:
@@ -61,43 +79,29 @@
61
79
  // option of the $.ajax upload requests:
62
80
  dataType: 'json',
63
81
 
64
- // Function returning the current number of files,
65
- // used by the maxNumberOfFiles validation:
66
- getNumberOfFiles: function () {
67
- return this.filesContainer.children().length;
68
- },
69
-
70
- // Callback to retrieve the list of files from the server response:
71
- getFilesFromResponse: function (data) {
72
- if (data.result && $.isArray(data.result.files)) {
73
- return data.result.files;
74
- }
75
- return [];
76
- },
77
-
78
82
  // The add callback is invoked as soon as files are added to the fileupload
79
83
  // widget (via file input selection, drag & drop or add API call).
80
84
  // See the basic file upload widget for more information:
81
85
  add: function (e, data) {
82
- var $this = $(this),
83
- that = $this.data('blueimp-fileupload') ||
84
- $this.data('fileupload'),
86
+ var that = $(this).data('blueimp-fileupload') ||
87
+ $(this).data('fileupload'),
85
88
  options = that.options,
86
89
  files = data.files;
87
- data.process(function () {
88
- return $this.fileupload('process', data);
89
- }).always(function () {
90
+ $(this).fileupload('process', data).done(function () {
91
+ that._adjustMaxNumberOfFiles(-files.length);
92
+ data.maxNumberOfFilesAdjusted = true;
93
+ data.files.valid = data.isValidated = that._validate(files);
90
94
  data.context = that._renderUpload(files).data('data', data);
91
- that._renderPreviews(data);
92
95
  options.filesContainer[
93
96
  options.prependFiles ? 'prepend' : 'append'
94
97
  ](data.context);
98
+ that._renderPreviews(data);
95
99
  that._forceReflow(data.context);
96
100
  that._transition(data.context).done(
97
101
  function () {
98
102
  if ((that._trigger('added', e, data) !== false) &&
99
103
  (options.autoUpload || data.autoUpload) &&
100
- data.autoUpload !== false && !data.files.error) {
104
+ data.autoUpload !== false && data.isValidated) {
101
105
  data.submit();
102
106
  }
103
107
  }
@@ -108,6 +112,15 @@
108
112
  send: function (e, data) {
109
113
  var that = $(this).data('blueimp-fileupload') ||
110
114
  $(this).data('fileupload');
115
+ if (!data.isValidated) {
116
+ if (!data.maxNumberOfFilesAdjusted) {
117
+ that._adjustMaxNumberOfFiles(-data.files.length);
118
+ data.maxNumberOfFilesAdjusted = true;
119
+ }
120
+ if (!that._validate(data.files)) {
121
+ return false;
122
+ }
123
+ }
111
124
  if (data.context && data.dataType &&
112
125
  data.dataType.substr(0, 6) === 'iframe') {
113
126
  // Iframe Transport does not support progress events.
@@ -129,9 +142,7 @@
129
142
  done: function (e, data) {
130
143
  var that = $(this).data('blueimp-fileupload') ||
131
144
  $(this).data('fileupload'),
132
- getFilesFromResponse = data.getFilesFromResponse ||
133
- that.options.getFilesFromResponse,
134
- files = getFilesFromResponse(data),
145
+ files = that._getFilesFromResponse(data),
135
146
  template,
136
147
  deferred;
137
148
  if (data.context) {
@@ -139,6 +150,9 @@
139
150
  var file = files[index] ||
140
151
  {error: 'Empty file upload result'},
141
152
  deferred = that._addFinishedDeferreds();
153
+ if (file.error) {
154
+ that._adjustMaxNumberOfFiles(1);
155
+ }
142
156
  that._transition($(this)).done(
143
157
  function () {
144
158
  var node = $(this);
@@ -157,6 +171,17 @@
157
171
  );
158
172
  });
159
173
  } else {
174
+ if (files.length) {
175
+ $.each(files, function (index, file) {
176
+ if (data.maxNumberOfFilesAdjusted && file.error) {
177
+ that._adjustMaxNumberOfFiles(1);
178
+ } else if (!data.maxNumberOfFilesAdjusted &&
179
+ !file.error) {
180
+ that._adjustMaxNumberOfFiles(-1);
181
+ }
182
+ });
183
+ data.maxNumberOfFilesAdjusted = true;
184
+ }
160
185
  template = that._renderDownload(files)
161
186
  .appendTo(that.options.filesContainer);
162
187
  that._forceReflow(template);
@@ -177,6 +202,9 @@
177
202
  $(this).data('fileupload'),
178
203
  template,
179
204
  deferred;
205
+ if (data.maxNumberOfFilesAdjusted) {
206
+ that._adjustMaxNumberOfFiles(data.files.length);
207
+ }
180
208
  if (data.context) {
181
209
  data.context.each(function (index) {
182
210
  if (data.errorThrown !== 'abort') {
@@ -295,12 +323,6 @@
295
323
  }
296
324
  );
297
325
  },
298
- processstart: function () {
299
- $(this).addClass('fileupload-processing');
300
- },
301
- processstop: function () {
302
- $(this).removeClass('fileupload-processing');
303
- },
304
326
  // Callback for file deletion:
305
327
  destroy: function (e, data) {
306
328
  var that = $(this).data('blueimp-fileupload') ||
@@ -310,6 +332,7 @@
310
332
  that._transition(data.context).done(
311
333
  function () {
312
334
  $(this).remove();
335
+ that._adjustMaxNumberOfFiles(1);
313
336
  that._trigger('destroyed', e, data);
314
337
  }
315
338
  );
@@ -334,6 +357,13 @@
334
357
  return this._finishedUploads;
335
358
  },
336
359
 
360
+ _getFilesFromResponse: function (data) {
361
+ if (data.result && $.isArray(data.result.files)) {
362
+ return data.result.files;
363
+ }
364
+ return [];
365
+ },
366
+
337
367
  // Link handler, that allows to download files
338
368
  // by drag & drop of the links to the desktop:
339
369
  _enableDragToDesktop: function () {
@@ -347,10 +377,21 @@
347
377
  'DownloadURL',
348
378
  [type, name, url].join(':')
349
379
  );
350
- } catch (ignore) {}
380
+ } catch (err) {}
351
381
  });
352
382
  },
353
383
 
384
+ _adjustMaxNumberOfFiles: function (operand) {
385
+ if (typeof this.options.maxNumberOfFiles === 'number') {
386
+ this.options.maxNumberOfFiles += operand;
387
+ if (this.options.maxNumberOfFiles < 1) {
388
+ this._disableFileInputButton();
389
+ } else {
390
+ this._enableFileInputButton();
391
+ }
392
+ }
393
+ },
394
+
354
395
  _formatFileSize: function (bytes) {
355
396
  if (typeof bytes !== 'number') {
356
397
  return '';
@@ -406,6 +447,46 @@
406
447
  this._formatFileSize(data.total);
407
448
  },
408
449
 
450
+ _hasError: function (file) {
451
+ if (file.error) {
452
+ return file.error;
453
+ }
454
+ // The number of added files is subtracted from
455
+ // maxNumberOfFiles before validation, so we check if
456
+ // maxNumberOfFiles is below 0 (instead of below 1):
457
+ if (this.options.maxNumberOfFiles < 0) {
458
+ return 'Maximum number of files exceeded';
459
+ }
460
+ // Files are accepted if either the file type or the file name
461
+ // matches against the acceptFileTypes regular expression, as
462
+ // only browsers with support for the File API report the type:
463
+ if (!(this.options.acceptFileTypes.test(file.type) ||
464
+ this.options.acceptFileTypes.test(file.name))) {
465
+ return 'Filetype not allowed';
466
+ }
467
+ if (this.options.maxFileSize &&
468
+ file.size > this.options.maxFileSize) {
469
+ return 'File is too big';
470
+ }
471
+ if (typeof file.size === 'number' &&
472
+ file.size < this.options.minFileSize) {
473
+ return 'File is too small';
474
+ }
475
+ return null;
476
+ },
477
+
478
+ _validate: function (files) {
479
+ var that = this,
480
+ valid = !!files.length;
481
+ $.each(files, function (index, file) {
482
+ file.error = that._hasError(file);
483
+ if (file.error) {
484
+ valid = false;
485
+ }
486
+ });
487
+ return valid;
488
+ },
489
+
409
490
  _renderTemplate: function (func, files) {
410
491
  if (!func) {
411
492
  return $();
@@ -421,10 +502,63 @@
421
502
  return $(this.options.templatesContainer).html(result).children();
422
503
  },
423
504
 
505
+ _renderPreview: function (file, node) {
506
+ var that = this,
507
+ options = this.options,
508
+ dfd = $.Deferred();
509
+ return ((loadImage && loadImage(
510
+ file,
511
+ function (img) {
512
+ node.append(img);
513
+ that._forceReflow(node);
514
+ that._transition(node).done(function () {
515
+ dfd.resolveWith(node);
516
+ });
517
+ if (!$.contains(that.document[0].body, node[0])) {
518
+ // If the element is not part of the DOM,
519
+ // transition events are not triggered,
520
+ // so we have to resolve manually:
521
+ dfd.resolveWith(node);
522
+ }
523
+ node.on('remove', function () {
524
+ // If the element is removed before the
525
+ // transition finishes, transition events are
526
+ // not triggered, resolve manually:
527
+ dfd.resolveWith(node);
528
+ });
529
+ },
530
+ {
531
+ maxWidth: options.previewMaxWidth,
532
+ maxHeight: options.previewMaxHeight,
533
+ canvas: options.previewAsCanvas
534
+ }
535
+ )) || dfd.resolveWith(node)) && dfd;
536
+ },
537
+
424
538
  _renderPreviews: function (data) {
425
- data.context.find('.preview').each(function (index, elm) {
426
- $(elm).append(data.files[index].preview);
539
+ var that = this,
540
+ options = this.options;
541
+ data.context.find('.preview span').each(function (index, element) {
542
+ var file = data.files[index];
543
+ if (options.previewSourceFileTypes.test(file.type) &&
544
+ ($.type(options.previewSourceMaxFileSize) !== 'number' ||
545
+ file.size < options.previewSourceMaxFileSize)) {
546
+ that._processingQueue = that._processingQueue.pipe(function () {
547
+ var dfd = $.Deferred(),
548
+ ev = $.Event('previewdone', {
549
+ target: element
550
+ });
551
+ that._renderPreview(file, $(element)).done(
552
+ function () {
553
+ that._trigger(ev.type, ev, data);
554
+ dfd.resolveWith(that);
555
+ }
556
+ );
557
+ return dfd.promise();
558
+ });
559
+ }
427
560
  });
561
+ return this._processingQueue;
428
562
  },
429
563
 
430
564
  _renderUpload: function (files) {
@@ -435,6 +569,7 @@
435
569
  },
436
570
 
437
571
  _renderDownload: function (files) {
572
+ console.log(files);
438
573
  return this._renderTemplate(
439
574
  this.options.downloadTemplate,
440
575
  files
@@ -597,14 +732,54 @@
597
732
  }
598
733
  },
599
734
 
735
+ _stringToRegExp: function (str) {
736
+ var parts = str.split('/'),
737
+ modifiers = parts.pop();
738
+ parts.shift();
739
+ return new RegExp(parts.join('/'), modifiers);
740
+ },
741
+
742
+ _initRegExpOptions: function () {
743
+ var options = this.options;
744
+ if ($.type(options.acceptFileTypes) === 'string') {
745
+ options.acceptFileTypes = this._stringToRegExp(
746
+ options.acceptFileTypes
747
+ );
748
+ }
749
+ if ($.type(options.previewSourceFileTypes) === 'string') {
750
+ options.previewSourceFileTypes = this._stringToRegExp(
751
+ options.previewSourceFileTypes
752
+ );
753
+ }
754
+ },
755
+
600
756
  _initSpecialOptions: function () {
601
757
  this._super();
602
758
  this._initFilesContainer();
603
759
  this._initTemplates();
760
+ this._initRegExpOptions();
761
+ },
762
+
763
+ _setOption: function (key, value) {
764
+ this._super(key, value);
765
+ if (key === 'maxNumberOfFiles') {
766
+ this._adjustMaxNumberOfFiles(0);
767
+ }
604
768
  },
605
769
 
606
770
  _create: function () {
607
771
  this._super();
772
+ this._refreshOptionsList.push(
773
+ 'filesContainer',
774
+ 'uploadTemplateId',
775
+ 'downloadTemplateId'
776
+ );
777
+ if (!this._processingQueue) {
778
+ this._processingQueue = $.Deferred().resolveWith(this).promise();
779
+ this.process = function () {
780
+ return this._processingQueue;
781
+ };
782
+ }
608
783
  this._resetFinishedDeferreds();
609
784
  },
610
785