activeadmin_select_many 0.2.8 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +20 -13
- data/app/assets/javascripts/activeadmin/select_many.js +151 -72
- data/lib/activeadmin/select_many/version.rb +1 -1
- data/lib/formtastic/inputs/select_many_input.rb +58 -32
- data/lib/formtastic/inputs/select_one_input.rb +23 -16
- metadata +134 -13
- data/.gitignore +0 -3
- data/Gemfile +0 -4
- data/activeadmin_select_many.gemspec +0 -19
- data/screenshot.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 125c98dc457c8e510aa9e35d0c03c9d86341a42c6395cbd5da501f32a0782ab3
|
4
|
+
data.tar.gz: aa9ab407d84de81df360209eba4c868da7232805fe6606d19d2e3b3c74d00279
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f40eda600327c6a7262548e7052ae0662c65b88a40cdd21d4138d7b2ce9e4df37e9884384d23dc34e34236f778e876e2a7d48f575d11af8d361598189e7b3ffa
|
7
|
+
data.tar.gz: 5e0d0b7b131174658ad5dfde9c235dedb5ddfb09c703efed47ea4141b4b0ac06fec1f3591c4ab6b790167f1793570f70a5d2b3a557b7196bed4bb993f4ed9035
|
data/README.md
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
# ActiveAdmin Select Many [![Gem Version](https://badge.fury.io/rb/activeadmin_select_many.svg)](https://badge.fury.io/rb/activeadmin_select_many)
|
2
2
|
|
3
|
-
An Active Admin plugin which improves one-to-many / many-to-many / many-to-one associations selection using 2 new inputs: **select_many** and **select_one** (jQuery required)
|
3
|
+
An Active Admin plugin which improves one-to-many / many-to-many / many-to-one associations selection using 2 new inputs: **select_many** and **select_one** (jQuery required).
|
4
4
|
|
5
5
|
Features for *select_many*:
|
6
|
-
- search box
|
7
|
-
- available items on the left, selected items on the right
|
8
|
-
- local/remote collections
|
9
|
-
- double click to add/remove items
|
10
|
-
- sortable (with up/down buttons)
|
6
|
+
- search box;
|
7
|
+
- available items on the left, selected items on the right;
|
8
|
+
- local/remote collections;
|
9
|
+
- double click to add/remove items;
|
10
|
+
- sortable (with up/down buttons);
|
11
|
+
- key bindings to improve accessibility.
|
11
12
|
|
12
13
|
Features for *select_one*:
|
13
|
-
- search box
|
14
|
-
- selected items on the right
|
15
|
-
- remote collections
|
16
|
-
- counter of items found
|
17
|
-
- can be used as filter
|
14
|
+
- search box;
|
15
|
+
- selected items on the right;
|
16
|
+
- remote collections;
|
17
|
+
- counter of items found;
|
18
|
+
- can be used as filter;
|
19
|
+
- key bindings to improve accessibility.
|
18
20
|
|
19
21
|
![screenshot](screenshot.png)
|
20
22
|
|
@@ -36,6 +38,7 @@ Features for *select_one*:
|
|
36
38
|
- **collection**: local collection
|
37
39
|
- **counter_limit**: if results count is greater than or equal to this limit a '+' is shown
|
38
40
|
- **filter_form**: for *select_one* only, allow to use it as filter
|
41
|
+
- **include_blank**: for *select_one* only, default true, allow to include a blank value on top
|
39
42
|
- **member_label**: key to use as text for select options
|
40
43
|
- **placeholder**: placeholder string for search box
|
41
44
|
- **remote_collection**: JSON path
|
@@ -44,7 +47,7 @@ Features for *select_one*:
|
|
44
47
|
- **size**: number of rows of both the selects (default: 4)
|
45
48
|
- **sortable**: set to true to enable sortable buttons (default: not set)
|
46
49
|
|
47
|
-
##
|
50
|
+
## Examples with select_many
|
48
51
|
|
49
52
|
Add to ActiveAdmin model config, in *form* block.
|
50
53
|
|
@@ -82,7 +85,7 @@ ActiveAdmin.register Tag do
|
|
82
85
|
end
|
83
86
|
```
|
84
87
|
|
85
|
-
##
|
88
|
+
## Examples with select_one
|
86
89
|
|
87
90
|
In a form:
|
88
91
|
|
@@ -92,6 +95,10 @@ As filter:
|
|
92
95
|
|
93
96
|
`filter :article_id_eq, as: :select_one, filter_form: true, placeholder: 'Search...', search_param: 'title_contains', member_label: 'title', remote_collection: '/admin/articles.json'`
|
94
97
|
|
98
|
+
## Notes
|
99
|
+
|
100
|
+
- To use this plugins with ActiveAdmin 1.x please use the version 0.3.4
|
101
|
+
|
95
102
|
## Do you like it? Star it!
|
96
103
|
|
97
104
|
If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
|
@@ -1,15 +1,15 @@
|
|
1
|
-
function smActivate(
|
2
|
-
if(
|
3
|
-
var parent = $(this).closest(
|
1
|
+
function smActivate(target) {
|
2
|
+
if(target.tagName.toLowerCase() == 'option') {
|
3
|
+
var parent = $(this).closest('.select_many');
|
4
4
|
var opt = $(target);
|
5
|
-
var dst = parent.find(
|
6
|
-
dst.append(
|
5
|
+
var dst = parent.find($(this).data('select') == 'src' ? '[data-select="dst"]' : '[data-select="src"]');
|
6
|
+
dst.append($('<option>', { value: opt.val(), text: opt.text() }));
|
7
7
|
opt.remove();
|
8
|
-
smUpdateValues(
|
8
|
+
smUpdateValues(parent);
|
9
9
|
}
|
10
10
|
}
|
11
11
|
|
12
|
-
function smDebounce(
|
12
|
+
function smDebounce(func, wait, immediate) {
|
13
13
|
var timeout;
|
14
14
|
return function() {
|
15
15
|
var context = this, args = arguments;
|
@@ -24,120 +24,199 @@ function smDebounce( func, wait, immediate ) {
|
|
24
24
|
};
|
25
25
|
};
|
26
26
|
|
27
|
-
function smUpdateValues(
|
28
|
-
var cnt = 0, values = parent.find(
|
27
|
+
function smUpdateValues(parent) {
|
28
|
+
var cnt = 0, values = parent.find('.values');
|
29
29
|
values.empty();
|
30
|
-
parent.find(
|
31
|
-
values.append(
|
30
|
+
parent.find('[data-select="dst"] option').each(function() {
|
31
|
+
values.append($('<input>', { type: 'hidden', name: values.data('name'), value: $(this).val() }));
|
32
32
|
cnt++;
|
33
33
|
});
|
34
|
-
if(
|
35
|
-
parent.find(
|
34
|
+
if(cnt == 0) values.append($('<input>', { type: 'hidden', name: values.data('name') }));
|
35
|
+
parent.find('.selected span').text(' [' + cnt + ']');
|
36
|
+
parent.find('.available span').text(' [' + parent.find('[data-select="src"] option').length + ']');
|
36
37
|
}
|
37
38
|
|
38
|
-
$(document).ready(
|
39
|
-
$('.select_many.input select').on(
|
40
|
-
$.proxy(
|
39
|
+
$(document).ready(function() {
|
40
|
+
$('.select_many.input select').on('dblclick', function(event) {
|
41
|
+
$.proxy(smActivate, $(this))(event.target);
|
41
42
|
});
|
42
43
|
|
43
|
-
|
44
|
+
// --- select_many ----------------------------------------------------------
|
45
|
+
var onLocalSelect = smDebounce(function() {
|
44
46
|
var cnt = 0, search = $(this).val().toLowerCase();
|
45
|
-
$(this).closest(
|
46
|
-
var found = $(this).text().toLowerCase().indexOf(
|
47
|
-
$(this).toggle(
|
48
|
-
if(
|
47
|
+
$(this).closest('.select_many').find('[data-select="src"] option').each(function() {
|
48
|
+
var found = $(this).text().toLowerCase().indexOf(search) >= 0;
|
49
|
+
$(this).toggle(found);
|
50
|
+
if(found) cnt++;
|
49
51
|
});
|
50
|
-
$(this).parent().find(
|
51
|
-
}, 250
|
52
|
-
|
52
|
+
$(this).parent().find('.available span').text(' [' + cnt + ']');
|
53
|
+
}, 250);
|
54
|
+
|
55
|
+
var onRemoteSelect = smDebounce(function(event) {
|
53
56
|
var search = $(this).val().trim();
|
54
|
-
if(
|
55
|
-
$(this).data(
|
57
|
+
if($(this).data('searching') != '1' && search && $(this).data('last-search') != search) {
|
58
|
+
$(this).data('searching', '1');
|
59
|
+
$(this).data('last-search', search);
|
56
60
|
var _this = $(this);
|
57
61
|
var data = {}
|
58
62
|
var text_key = $(this).data('text');
|
59
63
|
var value_key = $(this).data('value');
|
60
|
-
var counter_limit = $(this).data('counter-limit') ? Number(
|
64
|
+
var counter_limit = $(this).data('counter-limit') ? Number($(this).data('counter-limit')) : 0;
|
61
65
|
data['q['+$(this).data('search')+']'] = search;
|
62
66
|
$.ajax({
|
63
67
|
context: _this,
|
64
68
|
data: data,
|
65
|
-
url: $(this).data(
|
66
|
-
complete: function(
|
67
|
-
$(this).data(
|
69
|
+
url: $(this).data('remote-collection'),
|
70
|
+
complete: function(req, status) {
|
71
|
+
$(this).data('searching', '');
|
68
72
|
},
|
69
|
-
success: function(
|
70
|
-
var select = $(this).closest(
|
73
|
+
success: function(data, status, req) {
|
74
|
+
var select = $(this).closest('.select_many').find('[data-select="src"]');
|
71
75
|
select.empty();
|
72
|
-
data.forEach(
|
73
|
-
select.append(
|
76
|
+
data.forEach(function(item) {
|
77
|
+
select.append($('<option>', { value: item[value_key], text: item[text_key] }));
|
74
78
|
});
|
75
|
-
$(this).parent().find(
|
79
|
+
$(this).parent().find('.available span').text(' [' + ((counter_limit > 0 && data.length >= counter_limit) ? (counter_limit + '+') : data.length) + ']');
|
76
80
|
},
|
77
81
|
});
|
78
82
|
}
|
79
|
-
}, 400
|
83
|
+
}, 400);
|
80
84
|
|
81
|
-
$('.select_many.input .search-select').each(
|
85
|
+
$('.select_many.input .search-select').each(function() {
|
82
86
|
var parent = $(this).parent();
|
83
|
-
parent.find(
|
84
|
-
parent.find(
|
85
|
-
$(this).on(
|
87
|
+
parent.find('.available').append('<span> [' + parent.find('[data-select="src"] option').length + ']</span>');
|
88
|
+
parent.find('.selected').append('<span> [' + parent.find('[data-select="dst"] option').length + ']</span>');
|
89
|
+
$(this).on('keydown', function(event) {
|
90
|
+
if(event.which == 13 || event.which == 40) { // enter or arrow down
|
91
|
+
event.preventDefault();
|
92
|
+
$(this).closest('.select_many').find('[data-select="src"]').focus();
|
93
|
+
}
|
94
|
+
else $.proxy($(this).data('remote-collection') ? onRemoteSelect : onLocalSelect, $(this))(event);
|
95
|
+
});
|
96
|
+
|
97
|
+
// --- key bindings -------------------------------------------------------
|
98
|
+
parent.find('[data-select="src"]').on('keydown', function(event) {
|
99
|
+
if(event.which == 13) { // enter
|
100
|
+
event.preventDefault();
|
101
|
+
var opts = $(this).find(':selected');
|
102
|
+
if(opts.length > 0) {
|
103
|
+
var next = $(opts[0]).next();
|
104
|
+
$.proxy(smActivate, $(this))(opts[0]);
|
105
|
+
if(next.length > 0) $(this).val(next.val());
|
106
|
+
}
|
107
|
+
}
|
108
|
+
else if(event.which == 9 || event.which == 39) { // tab or right arrow
|
109
|
+
event.preventDefault();
|
110
|
+
parent.find('[data-select="dst"]').focus();
|
111
|
+
}
|
112
|
+
else if(event.which == 38) { // up arrow
|
113
|
+
if($(this).find('option')[0] == $(this).find(':selected')[0]) {
|
114
|
+
event.preventDefault();
|
115
|
+
parent.find('.search-select').focus();
|
116
|
+
}
|
117
|
+
}
|
118
|
+
});
|
119
|
+
parent.find('[data-select="dst"]').on('keydown', function(event) {
|
120
|
+
if(event.which == 13) { // enter
|
121
|
+
event.preventDefault();
|
122
|
+
var opts = $(this).find(':selected');
|
123
|
+
if(opts.length > 0) {
|
124
|
+
var next = $(opts[0]).next();
|
125
|
+
$.proxy(smActivate, $(this))(opts[0]);
|
126
|
+
if(next.length > 0) $(this).val(next.val());
|
127
|
+
}
|
128
|
+
}
|
129
|
+
else if(event.which == 37) { // left arrow
|
130
|
+
event.preventDefault();
|
131
|
+
parent.find('[data-select="src"]').focus();
|
132
|
+
}
|
133
|
+
});
|
86
134
|
});
|
87
|
-
|
135
|
+
|
136
|
+
// --- buttons --------------------------------------------------------------
|
137
|
+
$('.select_many .add').on('click', function() {
|
88
138
|
var select = $(this).parent().prev();
|
89
|
-
var current = select.find(
|
90
|
-
if(
|
139
|
+
var current = select.find('option:selected')[0];
|
140
|
+
if(current) $.proxy(smActivate, select)(current);
|
91
141
|
});
|
92
|
-
$('.select_many .remove').on(
|
142
|
+
$('.select_many .remove').on('click', function() {
|
93
143
|
var select = $(this).parent().next();
|
94
|
-
var current = select.find(
|
95
|
-
if(
|
144
|
+
var current = select.find('option:selected')[0];
|
145
|
+
if(current) $.proxy(smActivate, select)(current);
|
96
146
|
});
|
97
|
-
$('.select_many [sortable] .move_up').on(
|
147
|
+
$('.select_many [sortable] .move_up').on('click', function() {
|
98
148
|
var select = $(this).parent().next();
|
99
|
-
var current = select.find(
|
100
|
-
if(
|
101
|
-
$(current).prev().before(
|
102
|
-
smUpdateValues(
|
149
|
+
var current = select.find('option:selected')[0];
|
150
|
+
if(current) {
|
151
|
+
$(current).prev().before(current);
|
152
|
+
smUpdateValues($(this).closest('.select_many'));
|
103
153
|
}
|
104
154
|
});
|
105
|
-
$('.select_many [sortable] .move_down').on(
|
155
|
+
$('.select_many [sortable] .move_down').on('click', function() {
|
106
156
|
var select = $(this).parent().next();
|
107
|
-
var current = select.find(
|
108
|
-
if(
|
109
|
-
$(current).next().after(
|
110
|
-
smUpdateValues(
|
157
|
+
var current = select.find('option:selected')[0];
|
158
|
+
if(current) {
|
159
|
+
$(current).next().after(current);
|
160
|
+
smUpdateValues($(this).closest('.select_many'));
|
111
161
|
}
|
112
162
|
});
|
113
163
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
164
|
+
// --- select one -----------------------------------------------------------
|
165
|
+
var onRemoteSelectOne = smDebounce(function(event) {
|
166
|
+
var search = $(this).val().trim();
|
167
|
+
var select = $(this).closest('.select_one').find('[data-select="src"]');;
|
168
|
+
if(select.data('searching') != '1' && search && select.data('last-search') != search) {
|
169
|
+
select.data('searching', '1');
|
170
|
+
select.data('last-search', search);
|
118
171
|
var data = {}
|
119
172
|
var search_key = $(this).data('search') ? $(this).data('search') : 'name_contains';
|
120
173
|
var value_key = $(this).data('value') ? $(this).data('value') : 'id';
|
121
174
|
var text_key = $(this).data('text') ? $(this).data('text') : 'name';
|
122
|
-
var counter_limit = $(this).data('counter-limit') ? Number(
|
123
|
-
data['q['+search_key+']'] =
|
175
|
+
var counter_limit = $(this).data('counter-limit') ? Number($(this).data('counter-limit')) : 0;
|
176
|
+
data['q['+search_key+']'] = search;
|
124
177
|
$.ajax({
|
125
178
|
context: select,
|
126
179
|
data: data,
|
127
|
-
url: $(this).data(
|
128
|
-
complete: function(
|
129
|
-
$(this).data(
|
180
|
+
url: $(this).data('remote-collection'),
|
181
|
+
complete: function(req, status) {
|
182
|
+
$(this).data('searching', '');
|
130
183
|
},
|
131
|
-
success: function(
|
132
|
-
var sel = $(this);
|
184
|
+
success: function(data, status, req) {
|
185
|
+
var first = false, sel = $(this);
|
133
186
|
sel.empty();
|
134
|
-
data
|
135
|
-
|
187
|
+
if(sel.data('include-blank')) sel.append($('<option>', { value: '', text: '' }));
|
188
|
+
data.forEach(function(item) {
|
189
|
+
sel.append($('<option>', { value: item[value_key], text: item[text_key] }));
|
190
|
+
if(!first) first = item[value_key];
|
136
191
|
});
|
137
|
-
sel.parent().find(
|
192
|
+
sel.parent().find('.status').text('[' + ((counter_limit > 0 && data.length >= counter_limit) ? (counter_limit + '+') : data.length) + ']');
|
193
|
+
if(first) sel.val(first);
|
138
194
|
},
|
139
195
|
});
|
140
196
|
}
|
141
|
-
}, 500
|
142
|
-
|
197
|
+
}, 500);
|
198
|
+
|
199
|
+
$('.select-one-inputs').each(function() {
|
200
|
+
$(this).find('.search-select').on('keydown', function(event) {
|
201
|
+
if(event.which == 38) { // up arrow
|
202
|
+
event.preventDefault();
|
203
|
+
var select = $(this).closest('.select-one-inputs').find('[data-select="src"]');
|
204
|
+
var prev = select.find(':selected').prev();
|
205
|
+
if(prev.length) select.val(prev.val());
|
206
|
+
}
|
207
|
+
else if(event.which == 40) { // down arrow
|
208
|
+
event.preventDefault();
|
209
|
+
var select = $(this).closest('.select-one-inputs').find('[data-select="src"]');
|
210
|
+
var next = select.find(':selected').next();
|
211
|
+
if(next.length) select.val(next.val());
|
212
|
+
}
|
213
|
+
else $.proxy(onRemoteSelectOne, $(this))(event);
|
214
|
+
});
|
215
|
+
$(this).find('[data-select="src"]').on('keydown', function(event) {
|
216
|
+
if(event.which == 37) { // left arrow
|
217
|
+
event.preventDefault();
|
218
|
+
$(this).closest('.select-one-inputs').find('.search-select').focus();
|
219
|
+
}
|
220
|
+
});
|
221
|
+
});
|
143
222
|
});
|
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Formtastic
|
2
4
|
module Inputs
|
3
5
|
class SelectManyInput < SelectInput
|
4
6
|
def to_html
|
5
|
-
options[:'data-remote-collection'] = options.delete(
|
7
|
+
options[:'data-remote-collection'] = options.delete(:remote_collection)
|
6
8
|
opts = { class: 'select-many-inputs' }
|
7
|
-
opts[:sortable] = options.delete(
|
9
|
+
opts[:sortable] = options.delete(:sortable) if options[:sortable]
|
8
10
|
input_wrapping do
|
9
11
|
label_html <<
|
10
|
-
template.content_tag(
|
12
|
+
template.content_tag(:div, opts) do
|
11
13
|
hidden_input <<
|
12
14
|
search_box_html <<
|
13
|
-
template.content_tag(
|
14
|
-
template.content_tag(
|
15
|
-
template.content_tag(
|
15
|
+
template.content_tag(:span, '', class: 'empty') <<
|
16
|
+
template.content_tag(:span, ::I18n.t('inputs.select_many.available'), class: 'available') <<
|
17
|
+
template.content_tag(:span, ::I18n.t('inputs.select_many.selected'), class: 'selected') <<
|
16
18
|
select_src_html <<
|
17
19
|
buttons_html <<
|
18
20
|
select_dst_html
|
@@ -21,48 +23,72 @@ module Formtastic
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def hidden_input
|
24
|
-
template.content_tag(
|
25
|
-
values = object.send(
|
26
|
-
values = [values] if values.is_a?
|
26
|
+
template.content_tag(:div, class: 'values', 'data-name': input_html_options[:name]) do
|
27
|
+
values = object.send(input_name)
|
28
|
+
values = [values] if values.is_a? Integer
|
27
29
|
values.each do |value|
|
28
|
-
template.concat template.hidden_field_tag(
|
30
|
+
template.concat template.hidden_field_tag(input_html_options[:name], value, {id: nil})
|
29
31
|
end if values
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
35
|
def buttons_html
|
34
|
-
template.content_tag(
|
35
|
-
template.link_to(
|
36
|
-
template.link_to(
|
37
|
-
template.link_to(
|
38
|
-
template.link_to(
|
36
|
+
template.content_tag(:div, class: 'buttons') do
|
37
|
+
template.link_to('→'.html_safe, 'Javascript:void(0)', class: 'add') +
|
38
|
+
template.link_to('←'.html_safe, 'Javascript:void(0)', class: 'remove') +
|
39
|
+
template.link_to('↑'.html_safe, 'Javascript:void(0)', class: 'move_up') +
|
40
|
+
template.link_to('↓'.html_safe, 'Javascript:void(0)', class: 'move_down')
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
44
|
def search_box_html
|
43
|
-
|
44
|
-
|
45
|
+
opts = {
|
46
|
+
id: nil,
|
47
|
+
class: 'search-select',
|
48
|
+
placeholder: options.delete(:placeholder),
|
49
|
+
'data-counter-limit': options[:counter_limit].to_i,
|
50
|
+
'data-remote-collection': options[:'data-remote-collection'],
|
51
|
+
'data-search': options[:search_param] ? options[:search_param] : 'name_contains',
|
52
|
+
'data-text': options[:member_label] ? options[:member_label] : (options[:text_key] ? options[:text_key] : 'name'),
|
53
|
+
'data-value': options[:value_key] ? options[:value_key] : 'id',
|
54
|
+
}
|
55
|
+
template.text_field_tag(nil, '', opts)
|
45
56
|
end
|
46
57
|
|
47
58
|
def select_src_html
|
48
|
-
coll =
|
49
|
-
[]
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
coll =
|
60
|
+
if options[:'data-remote-collection']
|
61
|
+
[]
|
62
|
+
else
|
63
|
+
# TODO: add option unique ?
|
64
|
+
selected = object.send(input_name)
|
65
|
+
selected = [selected] if selected.is_a? Integer
|
66
|
+
selected ? collection.select { |option| !selected.include?(option[1]) } : collection
|
67
|
+
end
|
68
|
+
opts = {
|
69
|
+
id: nil,
|
70
|
+
include_blank: false,
|
71
|
+
multiple: true,
|
72
|
+
name: nil,
|
73
|
+
size: options[:size] || 4,
|
74
|
+
'data-select': 'src'
|
75
|
+
}
|
76
|
+
template.select_tag nil, template.options_for_select(coll), input_options.merge(opts)
|
58
77
|
end
|
59
78
|
|
60
79
|
def select_dst_html
|
61
|
-
selected = options[:selected]
|
62
|
-
selected = [selected] if selected.is_a?
|
63
|
-
coll = selected ? collection.select { |option| selected.include?(
|
64
|
-
opts =
|
65
|
-
|
80
|
+
selected = options[:selected] || object.send(input_name)
|
81
|
+
selected = [selected] if selected.is_a? Integer
|
82
|
+
coll = selected ? collection.select { |option| selected.include?(option[1]) } : []
|
83
|
+
opts = {
|
84
|
+
id: nil,
|
85
|
+
include_blank: false,
|
86
|
+
multiple: true,
|
87
|
+
name: nil,
|
88
|
+
size: options[:size] || 4,
|
89
|
+
'data-select': 'dst'
|
90
|
+
}
|
91
|
+
template.select_tag nil, template.options_for_select(coll), input_options.merge(opts)
|
66
92
|
end
|
67
93
|
end
|
68
94
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Formtastic
|
2
4
|
module Inputs
|
3
5
|
class SelectOneInput < SelectInput
|
4
|
-
def input_options
|
5
|
-
|
6
|
-
end
|
6
|
+
# def input_options
|
7
|
+
# super.merge include_blank: false
|
8
|
+
# end
|
7
9
|
|
8
10
|
def input_wrapping(&block)
|
9
11
|
template.content_tag(options[:filter_form] ? :div : :li,
|
@@ -16,30 +18,35 @@ module Formtastic
|
|
16
18
|
opts = { class: 'select-one-inputs' }
|
17
19
|
input_wrapping do
|
18
20
|
label_html <<
|
19
|
-
template.content_tag(
|
21
|
+
template.content_tag(:div, opts) do
|
20
22
|
search_box <<
|
21
23
|
select_html <<
|
22
|
-
template.content_tag(
|
24
|
+
template.content_tag(:span, '', class: 'status')
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
29
|
def search_box
|
28
30
|
# TODO: remove text_key in next major version
|
29
|
-
|
30
|
-
|
31
|
+
opts = {
|
32
|
+
id: nil,
|
33
|
+
class: 'search-select',
|
34
|
+
placeholder: options[:placeholder],
|
35
|
+
'data-counter-limit': options[:counter_limit].to_i,
|
36
|
+
'data-msg': options[:msg_items],
|
37
|
+
'data-remote-collection': options[:remote_collection],
|
38
|
+
'data-search': options[:search_param] || 'name_contains',
|
39
|
+
'data-text': options[:member_label] || options[:text_key] || 'name',
|
40
|
+
'data-value': options[:value_key] || 'id'
|
41
|
+
}
|
42
|
+
template.text_field_tag(nil, '', opts)
|
31
43
|
end
|
32
44
|
|
33
45
|
def select_html
|
34
|
-
selected = options[:selected]
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
sel = template.options_for_select( [item], selected ) if item[1] == selected
|
39
|
-
break
|
40
|
-
end
|
41
|
-
end
|
42
|
-
builder.select(input_name, sel, input_options, input_html_options.merge( 'data-select': 'src' ) )
|
46
|
+
selected = options[:selected] || object.send(input_name)
|
47
|
+
opts = input_html_options.merge('data-select': 'src')
|
48
|
+
opts['data-include-blank'] = '1' if input_options[:include_blank]
|
49
|
+
template.select_tag input_name, template.options_for_select(collection, selected), input_options.merge(opts)
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeadmin_select_many
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mattia Roccoberton
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activeadmin
|
@@ -16,14 +16,140 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activestorage
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 6.0.3.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 6.0.3.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: capybara
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.33.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.33.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.13.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.13.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: puma
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 4.3.5
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 4.3.5
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec_junit_formatter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.4.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.4.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.0.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.0.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: selenium-webdriver
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.142.7
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 3.142.7
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.19.0
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.19.0
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 1.4.2
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.4.2
|
27
153
|
description: An Active Admin plugin which improves one-to-many and many-to-many associations
|
28
154
|
selection (jQuery required)
|
29
155
|
email: mat@blocknot.es
|
@@ -31,12 +157,9 @@ executables: []
|
|
31
157
|
extensions: []
|
32
158
|
extra_rdoc_files: []
|
33
159
|
files:
|
34
|
-
- ".gitignore"
|
35
|
-
- Gemfile
|
36
160
|
- LICENSE.txt
|
37
161
|
- README.md
|
38
162
|
- Rakefile
|
39
|
-
- activeadmin_select_many.gemspec
|
40
163
|
- app/assets/javascripts/activeadmin/select_many.js
|
41
164
|
- app/assets/stylesheets/activeadmin/_select_many.sass
|
42
165
|
- config/locales/en.yml
|
@@ -46,12 +169,11 @@ files:
|
|
46
169
|
- lib/activeadmin_select_many.rb
|
47
170
|
- lib/formtastic/inputs/select_many_input.rb
|
48
171
|
- lib/formtastic/inputs/select_one_input.rb
|
49
|
-
- screenshot.png
|
50
172
|
homepage: https://github.com/blocknotes/activeadmin_select_many
|
51
173
|
licenses:
|
52
174
|
- MIT
|
53
175
|
metadata: {}
|
54
|
-
post_install_message:
|
176
|
+
post_install_message:
|
55
177
|
rdoc_options: []
|
56
178
|
require_paths:
|
57
179
|
- lib
|
@@ -66,9 +188,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
188
|
- !ruby/object:Gem::Version
|
67
189
|
version: '0'
|
68
190
|
requirements: []
|
69
|
-
|
70
|
-
|
71
|
-
signing_key:
|
191
|
+
rubygems_version: 3.0.3
|
192
|
+
signing_key:
|
72
193
|
specification_version: 4
|
73
194
|
summary: SelectMany plugin for ActiveAdmin
|
74
195
|
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
lib = File.expand_path('../lib', __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'activeadmin/select_many/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = 'activeadmin_select_many'
|
7
|
-
spec.version = ActiveAdmin::SelectMany::VERSION
|
8
|
-
spec.summary = 'SelectMany plugin for ActiveAdmin'
|
9
|
-
spec.description = 'An Active Admin plugin which improves one-to-many and many-to-many associations selection (jQuery required)'
|
10
|
-
spec.license = 'MIT'
|
11
|
-
spec.authors = ['Mattia Roccoberton']
|
12
|
-
spec.email = 'mat@blocknot.es'
|
13
|
-
spec.homepage = 'https://github.com/blocknotes/activeadmin_select_many'
|
14
|
-
|
15
|
-
spec.files = `git ls-files -z`.split("\x0")
|
16
|
-
spec.require_paths = ['lib']
|
17
|
-
|
18
|
-
spec.add_runtime_dependency 'activeadmin', '~> 1.0'
|
19
|
-
end
|
data/screenshot.png
DELETED
Binary file
|