simple_form_bs5_file_input 0.0.2 → 0.0.3

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.
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: