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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +22 -0
- data/assets/javascripts/simple_form_bs5_file_input.js +116 -20
- data/assets/stylesheets/simple_form_bs5_file_input.sass +6 -0
- data/config/locales/en.yml +3 -0
- data/config/locales/fr.yml +4 -1
- data/lib/has_one_attached_deletable.rb +2 -1
- data/lib/simple_form_bs5_file_input/single_deletable_file_input.rb +60 -10
- data/lib/simple_form_bs5_file_input/version.rb +1 -1
- data/pkg/simple_form_bs5_file_input-0.0.2.gem +0 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3644590aace1052e9505f4784b7146dbde206dc2297a9b9336eada0eb954fac
|
4
|
+
data.tar.gz: 803d6a3b7a7ef3d2165015d5a80600a09fcd940276e86814407b400306d7d555
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dd7c7a363de204dcdcd6cd50810403e796cd5a35bc03e4c827d516e4a719940941bc0f194e42f4a3457cfb34694f5f1391ba084ebbe5fc4d531d9e874d413e8
|
7
|
+
data.tar.gz: 6e98d851b926ec6cd7f60dff3d79bb15a460ecb4e3335da23f8c15e6e9d3a180f0518cce22a3aa2a0f9717ff0e692441debec8a80bff56fb6b9f3cf126d5a505
|
data/Gemfile.lock
CHANGED
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
|
-
|
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-
|
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
|
-
|
14
|
+
onFileSelected: function () {
|
15
15
|
'use strict';
|
16
16
|
var $scope = $(this).parents('.js-sdfi-deletable-file'),
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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(
|
26
|
-
$('.js-sdfi-deletable-
|
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
|
-
|
29
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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.
|
47
|
-
$('input[type="file"]', $(field)).on('change', this.
|
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
|
|
data/config/locales/en.yml
CHANGED
data/config/locales/fr.yml
CHANGED
@@ -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.
|
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-
|
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,
|
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
|
60
|
+
def input_delete_name
|
65
61
|
"#{@builder.object_name}[#{attribute_name.to_s}_delete]"
|
66
62
|
end
|
67
63
|
|
68
|
-
def
|
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
|
Binary file
|
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.
|
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:
|