activeadmin_select_many 0.2.8 → 0.3.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
2
  SHA1:
3
- metadata.gz: 3a289f4b6418d0af92538f32caed2af60a8149d6
4
- data.tar.gz: 37deed25511b1de438cae523b52a0f4c627d2d4e
3
+ metadata.gz: 2f658ea409967f4e0cfe78f48dd192d4047b0050
4
+ data.tar.gz: 4275e93e2a65befd4e712b3b884fe278bcd4c3c2
5
5
  SHA512:
6
- metadata.gz: a7774b3c4765e20abf7a18379a86f7faf0482c771fac313320bacb555e4a69c440c765da602c1ead8d93952e68a2acfc98d4ec0d626c22cc53f851f55d2242c9
7
- data.tar.gz: f7c76a2763f1a7977ea28e17eafbf1f7dde25a784f715d399f2f7b550f370573dd54161de5326e6e0c21ecd11660e6197f06cf3a90b79080ec4406583e42fc22
6
+ metadata.gz: 7d72c06453f4c81bb5fe90884ad92564e8f1f7ad5068db2e5bcc71bbb027e483e2e55945dc1aa8ad66c5da67614c097649bf84480ddfea32151b80cbc7edbdfe
7
+ data.tar.gz: 0e9e9dbc6d36d9c0757ca672d43478a081bf4f6806c49f69a83939eecc386ff8133fbf6846ed540d864e0814c8fede3735243978c4ffbed91cb4fefb01cf6d86
data/README.md CHANGED
@@ -8,6 +8,7 @@ Features for *select_many*:
8
8
  - local/remote collections
9
9
  - double click to add/remove items
10
10
  - sortable (with up/down buttons)
11
+ - key bindings to improve accessibility
11
12
 
12
13
  Features for *select_one*:
13
14
  - search box
@@ -15,6 +16,7 @@ Features for *select_one*:
15
16
  - remote collections
16
17
  - counter of items found
17
18
  - can be used as filter
19
+ - key bindings to improve accessibility
18
20
 
19
21
  ![screenshot](screenshot.png)
20
22
 
@@ -40,6 +40,7 @@ $(document).ready( function() {
40
40
  $.proxy( smActivate, $(this) )( event.target );
41
41
  });
42
42
 
43
+ // --- select_many ----------------------------------------------------------
43
44
  var onLocalSelect = smDebounce( function() {
44
45
  var cnt = 0, search = $(this).val().toLowerCase();
45
46
  $(this).closest( '.select_many' ).find( '[data-select="src"] option' ).each( function() {
@@ -49,10 +50,12 @@ $(document).ready( function() {
49
50
  });
50
51
  $(this).parent().find( '.available span' ).text( ' [' + cnt + ']' );
51
52
  }, 250 );
52
- var onRemoteSelect = smDebounce( function() {
53
+
54
+ var onRemoteSelect = smDebounce( function( event ) {
53
55
  var search = $(this).val().trim();
54
- if( search != '' && $(this).data( 'searching' ) != '1' ) {
56
+ if( $(this).data( 'searching' ) != '1' && search && $(this).data( 'last-search' ) != search ) {
55
57
  $(this).data( 'searching', '1' );
58
+ $(this).data( 'last-search', search );
56
59
  var _this = $(this);
57
60
  var data = {}
58
61
  var text_key = $(this).data('text');
@@ -82,8 +85,54 @@ $(document).ready( function() {
82
85
  var parent = $(this).parent();
83
86
  parent.find( '.available' ).append( '<span> [' + parent.find( '[data-select="src"] option' ).length + ']</span>' );
84
87
  parent.find( '.selected' ).append( '<span> [' + parent.find( '[data-select="dst"] option' ).length + ']</span>' );
85
- $(this).on( 'keyup', $(this).data( 'remote-collection' ) ? onRemoteSelect : onLocalSelect );
88
+ $(this).on( 'keydown', function( event ) {
89
+ if( event.which == 13 || event.which == 40 ) { // enter or arrow down
90
+ event.preventDefault();
91
+ $(this).closest( '.select_many' ).find( '[data-select="src"]' ).focus();
92
+ }
93
+ else $.proxy( $(this).data( 'remote-collection' ) ? onRemoteSelect : onLocalSelect, $(this) )( event );
94
+ });
95
+
96
+ // --- key bindings -------------------------------------------------------
97
+ parent.find( '[data-select="src"]' ).on( 'keydown', function( event ) {
98
+ if( event.which == 13 ) { // enter
99
+ event.preventDefault();
100
+ var opts = $(this).find( ':selected' );
101
+ if( opts.length > 0 ) {
102
+ var next = $( opts[0] ).next();
103
+ $.proxy( smActivate, $(this) )( opts[0] );
104
+ if( next.length > 0 ) $(this).val( next.val() );
105
+ }
106
+ }
107
+ else if( event.which == 9 || event.which == 39 ) { // tab or right arrow
108
+ event.preventDefault();
109
+ parent.find( '[data-select="dst"]' ).focus();
110
+ }
111
+ else if( event.which == 38 ) { // up arrow
112
+ if( $(this).find('option')[0] == $(this).find(':selected')[0] ) {
113
+ event.preventDefault();
114
+ parent.find( '.search-select' ).focus();
115
+ }
116
+ }
117
+ });
118
+ parent.find( '[data-select="dst"]' ).on( 'keydown', function( event ) {
119
+ if( event.which == 13 ) { // enter
120
+ event.preventDefault();
121
+ var opts = $(this).find( ':selected' );
122
+ if( opts.length > 0 ) {
123
+ var next = $( opts[0] ).next();
124
+ $.proxy( smActivate, $(this) )( opts[0] );
125
+ if( next.length > 0 ) $(this).val( next.val() );
126
+ }
127
+ }
128
+ else if( event.which == 37 ) { // left arrow
129
+ event.preventDefault();
130
+ parent.find( '[data-select="src"]' ).focus();
131
+ }
132
+ });
86
133
  });
134
+
135
+ // --- buttons --------------------------------------------------------------
87
136
  $('.select_many .add').on( 'click', function() {
88
137
  var select = $(this).parent().prev();
89
138
  var current = select.find( 'option:selected' )[0];
@@ -111,16 +160,19 @@ $(document).ready( function() {
111
160
  }
112
161
  });
113
162
 
163
+ // --- select one -----------------------------------------------------------
114
164
  var onRemoteSelectOne = smDebounce( function( event ) {
165
+ var search = $(this).val().trim();
115
166
  var select = $(this).next();
116
- if( select.data( 'searching' ) != '1' ) {
167
+ if( select.data( 'searching' ) != '1' && search && select.data( 'last-search' ) != search ) {
117
168
  select.data( 'searching', '1' );
169
+ select.data( 'last-search', search );
118
170
  var data = {}
119
171
  var search_key = $(this).data('search') ? $(this).data('search') : 'name_contains';
120
172
  var value_key = $(this).data('value') ? $(this).data('value') : 'id';
121
173
  var text_key = $(this).data('text') ? $(this).data('text') : 'name';
122
174
  var counter_limit = $(this).data('counter-limit') ? Number( $(this).data('counter-limit') ) : 0;
123
- data['q['+search_key+']'] = $(this).val();
175
+ data['q['+search_key+']'] = search;
124
176
  $.ajax({
125
177
  context: select,
126
178
  data: data,
@@ -139,5 +191,28 @@ $(document).ready( function() {
139
191
  });
140
192
  }
141
193
  }, 500 );
142
- $('.select-one-inputs > .search-select').on( 'keyup', onRemoteSelectOne );
194
+
195
+ $('.select-one-inputs').each( function() {
196
+ $(this).find( '.search-select' ).on( 'keydown', function( event ) {
197
+ if( event.which == 38 ) { // up arrow
198
+ event.preventDefault();
199
+ var select = $(this).closest( '.select-one-inputs' ).find( '[data-select="src"]' );
200
+ var prev = select.find( ':selected' ).prev();
201
+ if( prev.length ) select.val( prev.val() );
202
+ }
203
+ else if( event.which == 40 ) { // down arrow
204
+ event.preventDefault();
205
+ var select = $(this).closest( '.select-one-inputs' ).find( '[data-select="src"]' );
206
+ var next = select.find( ':selected' ).next();
207
+ if( next.length ) select.val( next.val() );
208
+ }
209
+ else $.proxy( onRemoteSelectOne, $(this) )( event );
210
+ });
211
+ $(this).find( '[data-select="src"]' ).on( 'keydown', function( event ) {
212
+ if( event.which == 37 ) { // left arrow
213
+ event.preventDefault();
214
+ $(this).closest( '.select-one-inputs' ).find( '.search-select' ).focus();
215
+ }
216
+ });
217
+ });
143
218
  });
@@ -1,5 +1,5 @@
1
1
  module ActiveAdmin
2
2
  module SelectMany
3
- VERSION = '0.2.8'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -10,9 +10,9 @@ module Formtastic
10
10
  template.content_tag( :div, opts ) do
11
11
  hidden_input <<
12
12
  search_box_html <<
13
- template.content_tag( :span, '', class: 'empty' ) <<
13
+ template.content_tag( :span, '', class: 'empty' ) <<
14
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, template.t( 'inputs.select_many.selected' ), class: 'selected' ) <<
16
16
  select_src_html <<
17
17
  buttons_html <<
18
18
  select_dst_html
@@ -40,8 +40,17 @@ module Formtastic
40
40
  end
41
41
 
42
42
  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 )
43
+ opts = {
44
+ id: nil,
45
+ class: 'search-select',
46
+ placeholder: options.delete( :placeholder ),
47
+ 'data-counter-limit': options[:counter_limit].to_i,
48
+ 'data-remote-collection': options[:'data-remote-collection'],
49
+ 'data-search': options[:search_param] ? options[:search_param] : 'name_contains',
50
+ 'data-text': options[:member_label] ? options[:member_label] : ( options[:text_key] ? options[:text_key] : 'name' ),
51
+ 'data-value': options[:value_key] ? options[:value_key] : 'id',
52
+ }
53
+ template.text_field_tag( nil, '', opts )
45
54
  end
46
55
 
47
56
  def select_src_html
@@ -26,8 +26,18 @@ module Formtastic
26
26
 
27
27
  def search_box
28
28
  # 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 )
29
+ opts = {
30
+ id: nil,
31
+ class: 'search-select',
32
+ placeholder: options[:placeholder],
33
+ 'data-counter-limit': options[:counter_limit].to_i,
34
+ 'data-msg': options[:msg_items],
35
+ 'data-remote-collection': options[:remote_collection],
36
+ 'data-search': options[:search_param] ? options[:search_param] : 'name_contains',
37
+ 'data-text': options[:member_label] ? options[:member_label] : ( options[:text_key] ? options[:text_key] : 'name' ),
38
+ 'data-value': options[:value_key] ? options[:value_key] : 'id',
39
+ }
40
+ template.text_field_tag( nil, '', opts )
31
41
  end
32
42
 
33
43
  def select_html
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.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-14 00:00:00.000000000 Z
11
+ date: 2017-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeadmin