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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3a289f4b6418d0af92538f32caed2af60a8149d6
4
- data.tar.gz: 37deed25511b1de438cae523b52a0f4c627d2d4e
2
+ SHA256:
3
+ metadata.gz: 125c98dc457c8e510aa9e35d0c03c9d86341a42c6395cbd5da501f32a0782ab3
4
+ data.tar.gz: aa9ab407d84de81df360209eba4c868da7232805fe6606d19d2e3b3c74d00279
5
5
  SHA512:
6
- metadata.gz: a7774b3c4765e20abf7a18379a86f7faf0482c771fac313320bacb555e4a69c440c765da602c1ead8d93952e68a2acfc98d4ec0d626c22cc53f851f55d2242c9
7
- data.tar.gz: f7c76a2763f1a7977ea28e17eafbf1f7dde25a784f715d399f2f7b550f370573dd54161de5326e6e0c21ecd11660e6197f06cf3a90b79080ec4406583e42fc22
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
- ## Example with select_many
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
- ## Example with select_one
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( target ) {
2
- if( target.tagName.toLowerCase() == 'option' ) {
3
- var parent = $(this).closest( '.select_many' );
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( $(this).data( 'select' ) == 'src' ? '[data-select="dst"]' : '[data-select="src"]' );
6
- dst.append( $('<option>', { value: opt.val(), text: opt.text() }) );
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( parent );
8
+ smUpdateValues(parent);
9
9
  }
10
10
  }
11
11
 
12
- function smDebounce( func, wait, immediate ) {
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( parent ) {
28
- var cnt = 0, values = parent.find( '.values' );
27
+ function smUpdateValues(parent) {
28
+ var cnt = 0, values = parent.find('.values');
29
29
  values.empty();
30
- parent.find( '[data-select="dst"] option' ).each( function() {
31
- values.append( $('<input>', { type: 'hidden', name: values.data( 'name' ), value: $(this).val() }) );
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( cnt == 0 ) values.append( $('<input>', { type: 'hidden', name: values.data( 'name' ) }) );
35
- parent.find( '.selected span' ).text( ' [' + cnt + ']' );
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( function() {
39
- $('.select_many.input select').on( 'dblclick', function( event ) {
40
- $.proxy( smActivate, $(this) )( event.target );
39
+ $(document).ready(function() {
40
+ $('.select_many.input select').on('dblclick', function(event) {
41
+ $.proxy(smActivate, $(this))(event.target);
41
42
  });
42
43
 
43
- var onLocalSelect = smDebounce( function() {
44
+ // --- select_many ----------------------------------------------------------
45
+ var onLocalSelect = smDebounce(function() {
44
46
  var cnt = 0, search = $(this).val().toLowerCase();
45
- $(this).closest( '.select_many' ).find( '[data-select="src"] option' ).each( function() {
46
- var found = $(this).text().toLowerCase().indexOf( search ) >= 0;
47
- $(this).toggle( found );
48
- if( found ) cnt++;
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( '.available span' ).text( ' [' + cnt + ']' );
51
- }, 250 );
52
- var onRemoteSelect = smDebounce( function() {
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( search != '' && $(this).data( 'searching' ) != '1' ) {
55
- $(this).data( 'searching', '1' );
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( $(this).data('counter-limit') ) : 0;
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( 'remote-collection' ),
66
- complete: function( req, status ) {
67
- $(this).data( 'searching', '' );
69
+ url: $(this).data('remote-collection'),
70
+ complete: function(req, status) {
71
+ $(this).data('searching', '');
68
72
  },
69
- success: function( data, status, req ) {
70
- var select = $(this).closest( '.select_many' ).find( '[data-select="src"]' );
73
+ success: function(data, status, req) {
74
+ var select = $(this).closest('.select_many').find('[data-select="src"]');
71
75
  select.empty();
72
- data.forEach( function( item ) {
73
- select.append( $('<option>', { value: item[value_key], text: item[text_key] }) );
76
+ data.forEach(function(item) {
77
+ select.append($('<option>', { value: item[value_key], text: item[text_key] }));
74
78
  });
75
- $(this).parent().find( '.available span' ).text( ' [' + ( ( counter_limit > 0 && data.length >= counter_limit ) ? ( counter_limit + '+' ) : data.length ) + ']' );
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( function() {
85
+ $('.select_many.input .search-select').each(function() {
82
86
  var parent = $(this).parent();
83
- parent.find( '.available' ).append( '<span> [' + parent.find( '[data-select="src"] option' ).length + ']</span>' );
84
- parent.find( '.selected' ).append( '<span> [' + parent.find( '[data-select="dst"] option' ).length + ']</span>' );
85
- $(this).on( 'keyup', $(this).data( 'remote-collection' ) ? onRemoteSelect : onLocalSelect );
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
- $('.select_many .add').on( 'click', function() {
135
+
136
+ // --- buttons --------------------------------------------------------------
137
+ $('.select_many .add').on('click', function() {
88
138
  var select = $(this).parent().prev();
89
- var current = select.find( 'option:selected' )[0];
90
- if( current ) $.proxy( smActivate, select )( current );
139
+ var current = select.find('option:selected')[0];
140
+ if(current) $.proxy(smActivate, select)(current);
91
141
  });
92
- $('.select_many .remove').on( 'click', function() {
142
+ $('.select_many .remove').on('click', function() {
93
143
  var select = $(this).parent().next();
94
- var current = select.find( 'option:selected' )[0];
95
- if( current ) $.proxy( smActivate, select )( current );
144
+ var current = select.find('option:selected')[0];
145
+ if(current) $.proxy(smActivate, select)(current);
96
146
  });
97
- $('.select_many [sortable] .move_up').on( 'click', function() {
147
+ $('.select_many [sortable] .move_up').on('click', function() {
98
148
  var select = $(this).parent().next();
99
- var current = select.find( 'option:selected' )[0];
100
- if( current ) {
101
- $(current).prev().before( current );
102
- smUpdateValues( $(this).closest( '.select_many' ) );
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( 'click', function() {
155
+ $('.select_many [sortable] .move_down').on('click', function() {
106
156
  var select = $(this).parent().next();
107
- var current = select.find( 'option:selected' )[0];
108
- if( current ) {
109
- $(current).next().after( current );
110
- smUpdateValues( $(this).closest( '.select_many' ) );
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
- var onRemoteSelectOne = smDebounce( function( event ) {
115
- var select = $(this).next();
116
- if( select.data( 'searching' ) != '1' ) {
117
- select.data( 'searching', '1' );
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( $(this).data('counter-limit') ) : 0;
123
- data['q['+search_key+']'] = $(this).val();
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( 'remote-collection' ),
128
- complete: function( req, status ) {
129
- $(this).data( 'searching', '' );
180
+ url: $(this).data('remote-collection'),
181
+ complete: function(req, status) {
182
+ $(this).data('searching', '');
130
183
  },
131
- success: function( data, status, req ) {
132
- var sel = $(this);
184
+ success: function(data, status, req) {
185
+ var first = false, sel = $(this);
133
186
  sel.empty();
134
- data.forEach( function( item ) {
135
- sel.append( $('<option>', { value: item[value_key], text: item[text_key] }) );
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( '.status' ).text( '[' + ( ( counter_limit > 0 && data.length >= counter_limit ) ? ( counter_limit + '+' ) : data.length ) + ']' );
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
- $('.select-one-inputs > .search-select').on( 'keyup', onRemoteSelectOne );
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,5 +1,5 @@
1
1
  module ActiveAdmin
2
2
  module SelectMany
3
- VERSION = '0.2.8'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -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( :remote_collection )
7
+ options[:'data-remote-collection'] = options.delete(:remote_collection)
6
8
  opts = { class: 'select-many-inputs' }
7
- opts[:sortable] = options.delete( :sortable ) if options[:sortable]
9
+ opts[:sortable] = options.delete(:sortable) if options[:sortable]
8
10
  input_wrapping do
9
11
  label_html <<
10
- template.content_tag( :div, opts ) do
12
+ template.content_tag(:div, opts) do
11
13
  hidden_input <<
12
14
  search_box_html <<
13
- template.content_tag( :span, '', class: 'empty' ) <<
14
- template.content_tag( :span, template.t( 'inputs.select_many.available' ), class: 'available' ) <<
15
- template.content_tag( :span, template.t( 'inputs.select_many.selected' ), class: 'selected' ) <<
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( :div, class: 'values', 'data-name': input_html_options[:name] ) do
25
- values = object.send( input_name )
26
- values = [values] if values.is_a? Fixnum
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( input_html_options[:name], value, {id: nil} )
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( :div, class: 'buttons' ) do
35
- template.link_to( '&rarr;'.html_safe, 'Javascript:void(0)', class: 'add' ) +
36
- template.link_to( '&larr;'.html_safe, 'Javascript:void(0)', class: 'remove' ) +
37
- template.link_to( '&uarr;'.html_safe, 'Javascript:void(0)', class: 'move_up' ) +
38
- template.link_to( '&darr;'.html_safe, 'Javascript:void(0)', class: 'move_down' )
36
+ template.content_tag(:div, class: 'buttons') do
37
+ template.link_to('&rarr;'.html_safe, 'Javascript:void(0)', class: 'add') +
38
+ template.link_to('&larr;'.html_safe, 'Javascript:void(0)', class: 'remove') +
39
+ template.link_to('&uarr;'.html_safe, 'Javascript:void(0)', class: 'move_up') +
40
+ template.link_to('&darr;'.html_safe, 'Javascript:void(0)', class: 'move_down')
39
41
  end
40
42
  end
41
43
 
42
44
  def search_box_html
43
- @opts ||= {id: nil, class: 'search-select', placeholder: options.delete( :placeholder ), 'data-remote-collection': options[:'data-remote-collection'], 'data-search': options[:search_param] ? options[:search_param] : 'name_contains', 'data-text': options[:member_label] ? options[:member_label] : ( options[:text_key] ? options[:text_key] : 'name' ), 'data-value': options[:value_key] ? options[:value_key] : 'id', 'data-counter-limit': options[:counter_limit].to_i}
44
- template.text_field_tag( nil, '', @opts )
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 = if options[:'data-remote-collection']
49
- []
50
- else
51
- # TODO: add option unique ?
52
- selected = object.send( input_name )
53
- selected = [selected] if selected.is_a? Fixnum
54
- selected ? collection.select { |option| !selected.include?( option[1] ) } : collection
55
- end
56
- opts = input_options.merge( name: nil, id: nil, multiple: true, 'data-select': 'src', size: options[:size] ? options[:size] : 4 )
57
- template.select_tag nil, template.options_for_select( coll ), opts
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] ? options[:selected] : object.send( input_name )
62
- selected = [selected] if selected.is_a? Fixnum
63
- coll = selected ? collection.select { |option| selected.include?( option[1] ) } : collection
64
- opts = input_options.merge( name: nil, id: nil, multiple: true, 'data-select': 'dst', size: options[:size] ? options[:size] : 4 )
65
- template.select_tag nil, template.options_for_select( coll ), opts
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
- super.merge include_blank: false
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( :div, opts ) do
21
+ template.content_tag(:div, opts) do
20
22
  search_box <<
21
23
  select_html <<
22
- template.content_tag( :span, '', class: 'status' )
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
- @opts ||= {id: nil, class: 'search-select', placeholder: options[:placeholder], 'data-remote-collection': options[:remote_collection], 'data-search': options[:search_param] ? options[:search_param] : 'name_contains', 'data-text': options[:member_label] ? options[:member_label] : ( options[:text_key] ? options[:text_key] : 'name' ), 'data-value': options[:value_key] ? options[:value_key] : 'id', 'data-msg': options[:msg_items], 'data-counter-limit': options[:counter_limit].to_i}
30
- template.text_field_tag( nil, '', @opts )
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] ? options[:selected] : object.send( input_name )
35
- sel = ''
36
- collection.each do |item|
37
- if item[1] == selected
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.2.8
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: 2017-10-14 00:00:00.000000000 Z
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: '1.0'
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: '1.0'
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
- rubyforge_project:
70
- rubygems_version: 2.6.13
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
@@ -1,3 +0,0 @@
1
- _misc/
2
-
3
- *.orig
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
@@ -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
Binary file