simple_form_bs5_file_input 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a01187ab37b834c60ee0739e576f7b35869e27657fd2ccecaf0cc75ecabc1aa
4
- data.tar.gz: 4f5b26770518772bf430cfffd9592125fd455b2e9247eb9af9eb20ebe0764121
3
+ metadata.gz: a3644590aace1052e9505f4784b7146dbde206dc2297a9b9336eada0eb954fac
4
+ data.tar.gz: 803d6a3b7a7ef3d2165015d5a80600a09fcd940276e86814407b400306d7d555
5
5
  SHA512:
6
- metadata.gz: 367087c90da736c938022e8bc4fd1bb6b449fc3ef7b8b60cbff799655d4133317aeb080f516e81548b9f22099b5e17a56ec8272a72f7031450017e39c9270393
7
- data.tar.gz: 01dba7a9ed7983a2cc748292f3e41031920499d4eebe16628e790f2d6ff03de51790fc7be7fd69333a92ac459377365527de43734794576958bcc8eb97d3e2b6
6
+ metadata.gz: 1dd7c7a363de204dcdcd6cd50810403e796cd5a35bc03e4c827d516e4a719940941bc0f194e42f4a3457cfb34694f5f1391ba084ebbe5fc4d531d9e874d413e8
7
+ data.tar.gz: 6e98d851b926ec6cd7f60dff3d79bb15a460ecb4e3335da23f8c15e6e9d3a180f0518cce22a3aa2a0f9717ff0e692441debec8a80bff56fb6b9f3cf126d5a505
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple_form_bs5_file_input (0.0.2)
4
+ simple_form_bs5_file_input (0.0.3)
5
5
  rails
6
6
  simple_form
7
7
 
data/README.md CHANGED
@@ -101,6 +101,28 @@ The new field is still compatible with the `direct_upload` param.
101
101
  Please remember to include the `activestorage.js` library in order to use the direct_upload feature.
102
102
  Direct upload will send the file BEFORE the page submission. You will get a progress bar in the file field while the file is uploading.
103
103
 
104
+ ## Resize
105
+
106
+ You can add an option to the field to resize the image after upload (of course it has to be an image!).
107
+ Add `resize: true` to your field.
108
+ You can also specify a ratio for the cropper. For example `resize: 1` will lock to aspect ratio to a square. Beware of the float constraints in rails. If you want a 4/3 ratio use `resize: 4/3.to_f` as 4/3 gives 1 in rails.
109
+
110
+
111
+ The resizer is based on [CropperJS](https://github.com/fengyuanchen/cropperjs) so you have to add cropper and jquery-cropper to your dependencies.
112
+ ```
113
+ yarn add cropperjs
114
+ yarn add jquery-cropper
115
+ ```
116
+ then include the js files in your application.js file
117
+ ```
118
+ //= require cropperjs/dist/cropper
119
+ //= require jquery-cropper/dist/jquery-cropper
120
+ ```
121
+ and include the css in your application.sass file
122
+ ```
123
+ @import 'cropperjs/dist/cropper'
124
+ ```
125
+
104
126
 
105
127
  ## I18n
106
128
 
@@ -1,40 +1,132 @@
1
- /*global $, document, window */
1
+ /*global $, document, window, bootstrap */
2
2
  window.inputSingleDeletableFile = {
3
- onDelete: function (e) {
3
+ onFileDelete: function (e) {
4
4
  'use strict';
5
5
  var $scope = $(this).parents('.js-sdfi-deletable-file');
6
6
  e.preventDefault();
7
7
  e.stopPropagation();
8
- $('.js-sdfi-deletable-file__hidden-field', $scope).val('true');
8
+ $('.js-sdfi-deletable-file__infos-field', $scope).val('');
9
+ $('.js-sdfi-deletable-file__delete-field', $scope).val('true');
9
10
  $('input[type="file"]', $scope).val('');
10
11
  $scope.removeClass('sdfi-deletable-file--with-file');
11
- // $('.custom-file-preview', scope).hide();
12
12
  },
13
13
 
14
- onChange: function () {
14
+ onFileSelected: function () {
15
15
  'use strict';
16
16
  var $scope = $(this).parents('.js-sdfi-deletable-file'),
17
- fileName = $(this).val()
18
- .split('\\')
19
- .pop(),
17
+ $resizeModal = $('.js-sdfi-deletable-file__resize', $scope),
18
+ files = this.files,
19
+ file,
20
20
  hasPreview = $('.js-sdfi-deletable-file__preview', $scope).length > 0,
21
+ hasResize = $resizeModal.length > 0,
22
+ modal,
21
23
  reader,
22
24
  size;
23
- if (fileName !== '') {
25
+
26
+ if (!files.length) {
27
+ return;
28
+ }
29
+
30
+ file = files[0];
31
+
32
+ if (!hasResize) {
33
+ // name display is delayed if we need to resize
24
34
  $scope.addClass('sdfi-deletable-file--with-file');
25
- $('.js-sdfi-deletable-file__label', $scope).html(fileName);
26
- $('.js-sdfi-deletable-file__hidden-field', $scope).val('');
35
+ $('.js-sdfi-deletable-file__label', $scope).html(file.name);
36
+ $('.js-sdfi-deletable-file__delete-field', $scope).val('');
37
+ }
38
+
39
+ if (/^image\/\w+$/.test(file.type) && (hasResize || hasPreview)) {
40
+ reader = new FileReader();
41
+ reader.readAsDataURL(file);
42
+ if (hasResize) {
43
+ reader.onload = function () {
44
+ modal = new bootstrap.Modal($resizeModal, {
45
+ backdrop: 'static',
46
+ keyboard: false
47
+ });
48
+ $resizeModal.attr('data-image-result', this.result);
49
+ $resizeModal.attr('data-filename', file.name);
50
+ modal.show();
51
+ };
52
+ } else if (hasPreview) {
53
+ size = $('.js-sdfi-deletable-file__preview', $scope).attr('data-size')
54
+ .split('x');
55
+ reader.onload = function (e) {
56
+ $('.js-sdfi-deletable-file__preview', $scope).html('<img src="' + e.target.result + '" width="' + size[0] + '" height="auto" class="img-fluid img-thumbnail">');
57
+ };
58
+ }
27
59
  }
28
- // preview
29
- if (hasPreview && this.files && this.files[0]) {
60
+ },
61
+
62
+ onResizeModalShown: function (e) {
63
+ 'use strict';
64
+ var $modal = $(e.target),
65
+ $scope = $modal.parents('.js-sdfi-deletable-file'),
66
+ $imgContainer = $('.js-sdfi-sdfi-deletable-file__resize-image', $scope),
67
+ $image,
68
+ image = $modal.attr('data-image-result'),
69
+ ratio = $imgContainer.attr('data-ratio');
70
+
71
+ $imgContainer.html('<img class="js-" src="' + image + '">');
72
+
73
+ $image = $('img', $imgContainer);
74
+ $image.css('opacity', 0);
75
+ setTimeout(function () {
76
+ // init cropper with a small delay
77
+ $image.cropper({
78
+ aspectRatio: ratio,
79
+ autoCropArea: 1,
80
+ movable: false,
81
+ guides: false,
82
+ background: false,
83
+ viewMode: 1,
84
+ zoomable: false,
85
+ crop: function (data) {
86
+ $('.js-sdfi-deletable-file__infos-field', $scope).val(JSON.stringify(data.detail));
87
+ }
88
+ });
89
+ $image.css('opacity', 1);
90
+ }, 100);
91
+ },
92
+
93
+ onResizeModalCancel: function (e) {
94
+ 'use strict';
95
+ var $scope = $(e.target).parents('.js-sdfi-deletable-file');
96
+ $('.js-sdfi-deletable-file__infos-field', $scope).val('');
97
+ $('.js-sdfi-deletable-file__delete-field', $scope).val('true');
98
+ $('input[type="file"]', $scope).val('');
99
+ $scope.removeClass('sdfi-deletable-file--with-file');
100
+ },
101
+
102
+ onResizeModalValidate: function (e) {
103
+ 'use strict';
104
+ var $scope = $(e.target).parents('.js-sdfi-deletable-file'),
105
+ $resizeModal = $('.js-sdfi-deletable-file__resize', $scope),
106
+ $imgContainer = $('.js-sdfi-sdfi-deletable-file__resize-image', $scope),
107
+ $image = $('img', $imgContainer),
108
+ filename = $resizeModal.attr('data-filename'),
109
+ hasPreview = $('.js-sdfi-deletable-file__preview', $scope).length > 0,
110
+ imageData,
111
+ resizeModal = $resizeModal[0],
112
+ modal = bootstrap.Modal.getInstance(resizeModal),
113
+ size;
114
+
115
+ $scope.addClass('sdfi-deletable-file--with-file');
116
+ $('.js-sdfi-deletable-file__label', $scope).html(filename);
117
+ $('.js-sdfi-deletable-file__delete-field', $scope).val('');
118
+
119
+ // set the preview if we have preview
120
+ if (hasPreview) {
30
121
  size = $('.js-sdfi-deletable-file__preview', $scope).attr('data-size')
31
122
  .split('x');
32
- reader = new FileReader();
33
- reader.onload = function (e) {
34
- $('.js-sdfi-deletable-file__preview', $scope).html('<img src="' + e.target.result + '" width="' + size[0] + '" height="auto" class="img-fluid img-thumbnail">');
35
- };
36
- reader.readAsDataURL(this.files[0]);
123
+ imageData = $image.data('cropper')
124
+ .getCroppedCanvas()
125
+ .toDataURL();
126
+
127
+ $('.js-sdfi-deletable-file__preview', $scope).html('<img src="' + imageData + '" width="' + size[0] + '" height="auto" class="img-fluid img-thumbnail">');
37
128
  }
129
+ modal.hide();
38
130
  },
39
131
 
40
132
  bindEvents: function (field) {
@@ -43,8 +135,12 @@ window.inputSingleDeletableFile = {
43
135
  $('.js-sdfi-deletable-file__change-btn', $(field)).on('click', function () {
44
136
  $('input[type="file"]', $(field)).click();
45
137
  });
46
- $('.js-sdfi-deletable-file__delete-btn', $(field)).on('click', this.onDelete);
47
- $('input[type="file"]', $(field)).on('change', this.onChange);
138
+ $('.js-sdfi-deletable-file__delete-btn', $(field)).on('click', this.onFileDelete);
139
+ $('input[type="file"]', $(field)).on('change', this.onFileSelected);
140
+
141
+ $('.js-sdfi-deletable-file__resize', field).on('shown.bs.modal', this.onResizeModalShown);
142
+ $('.js-sdfi-deletable-file__resize-cancel', field).on('click', this.onResizeModalCancel);
143
+ $('.js-sdfi-deletable-file__resize-validate', field).on('click', this.onResizeModalValidate);
48
144
  }
49
145
  };
50
146
 
@@ -67,6 +67,12 @@
67
67
  pointer-events: none
68
68
  width: 0%
69
69
 
70
+ &__resize
71
+ .sdfi-sdfi-deletable-file__resize-image
72
+ img
73
+ max-width: 100%
74
+ max-height: 300px
75
+
70
76
  &--with-file
71
77
  input[type='file']
72
78
  display: none
@@ -1,3 +1,6 @@
1
1
  en:
2
2
  simple_form_bs5_file_input:
3
+ modal_close: Close
4
+ modal_title: Resize the image
5
+ modal_validate: Validate
3
6
  replace_file: 'Change the file'
@@ -1,3 +1,6 @@
1
1
  fr:
2
2
  simple_form_bs5_file_input:
3
- replace_file: 'Remplacer le fichier'
3
+ modal_close: Fermer
4
+ modal_title: Cadrer l'image
5
+ modal_validate: Valider
6
+ replace_file: Remplacer le fichier
@@ -14,6 +14,7 @@ class ActiveRecord::Base
14
14
  define_method :"resize_#{name}" do
15
15
  return unless send(name).attached?
16
16
 
17
+
17
18
  params = JSON(send("#{name}_infos"))
18
19
  # reset the infos to prevent multiple resize if multiple save
19
20
  instance_variable_set :"@#{name}_infos", nil
@@ -30,7 +31,7 @@ class ActiveRecord::Base
30
31
  variant = Rails::VERSION::MAJOR >= 6 ? send(name).variant(**transformations)
31
32
  : send(name).variant(combine_options: transformations)
32
33
 
33
- variant_url = variant.processed.service_url
34
+ variant_url = variant.processed.url
34
35
  downloaded_image = URI.open(variant_url)
35
36
  attachable = { io: downloaded_image, filename: send(name).filename.to_s }
36
37
 
@@ -16,17 +16,13 @@ class SingleDeletableFileInput < SimpleForm::Inputs::Base
16
16
  <div class="sdfi-deletable-file__delete-btn js-sdfi-deletable-file__delete-btn"></div>
17
17
  <div class="sdfi-deletable-file__upload-background"></div>
18
18
  <div class="sdfi-deletable-file__upload-progress"></div>
19
- <input type="hidden" name="%s" class="js-sdfi-deletable-file__hidden-field" %s />
19
+ <input type="hidden" name="%s" class="js-sdfi-deletable-file__infos-field" %s />
20
+ <input type="hidden" name="%s" class="js-sdfi-deletable-file__delete-field" %s />
20
21
  </div>
21
22
  %s
23
+ %s
22
24
  </div>
23
- ', has_file_class, input_field(wrapper_options), field_classes(wrapper_options), change_file_text, field_id, existing_file_name_or_default_text, input_hidden_name, input_hidden_value, preview_div)
24
- end
25
-
26
- def preview_div
27
- if options[:preview]
28
- format('<div class="sdfi-deletable-file__preview js-sdfi-deletable-file__preview" data-size="%s">%s</div>', preview_image_width, preview_image_tag)
29
- end
25
+ ', has_file_class, input_field(wrapper_options), field_classes(wrapper_options), change_file_text, field_id, existing_file_name_or_default_text, input_infos_name, input_infos_value, input_delete_name, input_delete_value, preview_div, resize_div)
30
26
  end
31
27
 
32
28
  def has_file_class
@@ -61,14 +57,52 @@ class SingleDeletableFileInput < SimpleForm::Inputs::Base
61
57
  end
62
58
  end
63
59
 
64
- def input_hidden_name
60
+ def input_delete_name
65
61
  "#{@builder.object_name}[#{attribute_name.to_s}_delete]"
66
62
  end
67
63
 
68
- def input_hidden_value
64
+ def input_delete_value
69
65
  "value='true'" if @builder.object.send("#{attribute_name}_delete") == 'true'
70
66
  end
71
67
 
68
+ def input_infos_name
69
+ "#{@builder.object_name}[#{attribute_name.to_s}_infos]"
70
+ end
71
+
72
+ def input_infos_value
73
+ "value='#{@builder.object.send("#{attribute_name}_infos")}'" if @builder.object.send("#{attribute_name}_infos")
74
+ end
75
+
76
+ def preview_div
77
+ if options[:preview]
78
+ format('<div class="sdfi-deletable-file__preview js-sdfi-deletable-file__preview" data-size="%s">%s</div>', preview_image_width, preview_image_tag)
79
+ end
80
+ end
81
+
82
+ def resize_div
83
+ if options[:resize]
84
+ format('<div class="sdfi-deletable-file__resize js-sdfi-deletable-file__resize modal" tabindex="-1">
85
+ <div class="modal-dialog">
86
+ <div class="modal-content">
87
+ <div class="modal-header">
88
+ <h5 class="modal-title">%s</h5>
89
+ <button type="button" class="btn-close js-sdfi-deletable-file__resize-cancel" data-bs-dismiss="modal" aria-label="%s"></button>
90
+ </div>
91
+ <div class="modal-body">
92
+ <div class="sdfi-sdfi-deletable-file__resize-image js-sdfi-sdfi-deletable-file__resize-image" data-ratio="%s">
93
+
94
+ </div>
95
+ </div>
96
+ <div class="modal-footer">
97
+ <button type="button" class="btn btn-sm btn-secondary js-sdfi-deletable-file__resize-cancel" data-bs-dismiss="modal">%s</button>
98
+ <button type="button" class="btn btn-sm btn-primary js-sdfi-deletable-file__resize-validate">%s</button>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ </div>', modal_title, close_btn_text, resize_ratio, close_btn_text, validate_btn_text)
103
+ end
104
+ end
105
+
72
106
  private
73
107
 
74
108
  def file_attachment
@@ -83,6 +117,10 @@ class SingleDeletableFileInput < SimpleForm::Inputs::Base
83
117
  options[:preview] == true ? default_preview_image_width : options[:preview].to_i
84
118
  end
85
119
 
120
+ def resize_ratio
121
+ options[:resize] == true ? '' : options[:resize]
122
+ end
123
+
86
124
  def preview_image_tag
87
125
  if should_display_file? && file_attachment&.variable?
88
126
  image_tag(file_attachment.variant(resize: "#{preview_image_width}x").processed.url, class: 'img-fluid img-thumbnail', width: preview_image_width)
@@ -92,4 +130,16 @@ class SingleDeletableFileInput < SimpleForm::Inputs::Base
92
130
  def default_preview_image_width
93
131
  1000
94
132
  end
133
+
134
+ def modal_title
135
+ I18n.t('simple_form_bs5_file_input.modal_title')
136
+ end
137
+
138
+ def close_btn_text
139
+ I18n.t('simple_form_bs5_file_input.modal_close')
140
+ end
141
+
142
+ def validate_btn_text
143
+ I18n.t('simple_form_bs5_file_input.modal_validate')
144
+ end
95
145
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleFormBs5FileInput
2
- VERSION = "0.0.2".freeze
2
+ VERSION = "0.0.3".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_form_bs5_file_input
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre-andré Boissinot
@@ -89,6 +89,7 @@ files:
89
89
  - lib/simple_form_bs5_file_input/single_deletable_file_input.rb
90
90
  - lib/simple_form_bs5_file_input/version.rb
91
91
  - pkg/simple_form_bs5_file_input-0.0.1.gem
92
+ - pkg/simple_form_bs5_file_input-0.0.2.gem
92
93
  - simple_form_bs5_file_input.gemspec
93
94
  homepage: https://github.com/noesya/simple_form_bs5_file_input
94
95
  licenses: