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