better_select 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,12 @@
1
1
  [submodule "vendor"]
2
2
  path = vendor
3
3
  url = git@github.com:benastan/better_select.git
4
+ [submodule "vendor/better_select"]
5
+ path = vendor/better_select
6
+ url = git@github.com:benastan/better_select.git
7
+ [submodule "vendor/assets/better_select"]
8
+ path = vendor/assets/better_select
9
+ url = git@github.com:benastan/better_select.git
10
+ [submodule "vendor/assets/javascripts/better_select"]
11
+ path = vendor/assets/javascripts/better_select
12
+ url = git@github.com:benastan/better_select.git
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # BetterSelect
1
+ # BetterSelect (for Rails)
2
2
 
3
- TODO: Write a gem description
3
+ Easily get better HTML Select elements into your rails projects.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,17 +8,25 @@ Add this line to your application's Gemfile:
8
8
 
9
9
  gem 'better_select'
10
10
 
11
+ Or install it yourself as:
12
+
13
+ $ gem install better_select
14
+
11
15
  And then execute:
12
16
 
13
17
  $ bundle
14
18
 
15
- Or install it yourself as:
19
+ Add to application.js:
16
20
 
17
- $ gem install better_select
21
+ //= require 'better-select'
22
+
23
+ Add to any stylesheet:
24
+
25
+ @import 'better-select';
18
26
 
19
27
  ## Usage
20
28
 
21
- TODO: Write usage instructions here
29
+ See https://github.com/benastan/better_select for detailed usage.
22
30
 
23
31
  ## Contributing
24
32
 
@@ -16,4 +16,5 @@ Gem::Specification.new do |gem|
16
16
  gem.version = BetterSelect::VERSION
17
17
 
18
18
  gem.add_dependency "railties", "~> 3.1"
19
+ gem.add_dependency "underscore-rails"
19
20
  end
@@ -1,3 +1,3 @@
1
1
  module BetterSelect
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1 @@
1
+ //=require better_select/lib/better-select
@@ -0,0 +1,4 @@
1
+ compile:
2
+ coffee -co ./build ./lib/better-select.coffee
3
+ sass lib/better-select.css.scss > ./build/better-select.css
4
+
@@ -0,0 +1,68 @@
1
+ # BetterSelect
2
+
3
+ HTML5 still hasn't gotten these right. Here's a simple JavaScript HTMLSelectElement
4
+ replacer.
5
+
6
+ ## Installation
7
+
8
+ Add to HTML web page:
9
+
10
+ <!-- Underscore is BetterSelect's only dependency -->
11
+ <script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
12
+ <script type="text/javascript" src="https://raw.github.com/benastan/better_select/master/build/better-select.js"></script>
13
+
14
+ Or clone source:
15
+
16
+ git clone git@github.com:benastan/better_select.git
17
+
18
+ ## Usage
19
+
20
+ Plain JavaScript:
21
+
22
+ <select id="boring-select"><option>What a bore!</option><option>This
23
+ is boring!</option></select>
24
+
25
+ boring_select = document.getElementById('boring-select')
26
+ better_select = new BetterSelect(boring_select)
27
+
28
+ The BetterSelect instance offers a number of helpful properties, for
29
+ example:
30
+
31
+ better_select.select // HTML Element of the replacement select.
32
+ better_select.dropdown // HTML Element containing the new options list.
33
+ better_select.selected_option // HTML Element containing the new options list.
34
+
35
+ BetterSelect doesn't interfere with how the original select element
36
+ operates. When the form submits, the value still comes from the select
37
+ element itself.
38
+
39
+ Additionally, you can attach events to the original element the same way
40
+ as always:
41
+
42
+ ChangeHandler = function() { alert("It changed!") }
43
+ boring_select.addEventListener('change', ChangeHandler)
44
+
45
+ Or, with jQuery:
46
+
47
+ $(boring_select).on('change', ChangeHandler)
48
+
49
+ ## CSS
50
+
51
+ BetterSelect comes with a very limited amount of CSS -- just enough to
52
+ make BetterSelect functional. All other styling choices are up to you.
53
+
54
+ ## TODO
55
+
56
+ 1. There are still a few ways that BetterSelect does not quite feel like
57
+ a standard select element. One is that when you type out a value when
58
+ focused, BetterSelect only focuses based on the first letter.
59
+ 2. Create themes.
60
+ 3. Code clean up.
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create new Pull Request
@@ -42,8 +42,7 @@
42
42
 
43
43
  addClass = function(tgt, className) {
44
44
  var classes;
45
- classes = getClasses(tgt);
46
- if (classes.indexOf(className) === -1) {
45
+ if ((classes = getClasses(tgt)).indexOf(className) === -1) {
47
46
  classes.push(className);
48
47
  }
49
48
  return setClasses(tgt, classes);
@@ -51,7 +50,7 @@
51
50
 
52
51
  removeClass = function(tgt, className) {
53
52
  var classes, index;
54
- if (!(index = (classes = getClasses(tgt)).indexOf(className === -1))) {
53
+ if ((index = (classes = getClasses(tgt)).indexOf(className)) !== -1) {
55
54
  classes.splice(index, 1);
56
55
  }
57
56
  return setClasses(tgt, classes);
@@ -63,9 +62,7 @@
63
62
 
64
63
  build_element = function(what, orig, obj) {
65
64
  var elm;
66
- elm = $$(_.template(obj["" + what + "_template"])(obj["process_" + what](orig)));
67
- elm.orig = orig;
68
- orig.better_version = elm;
65
+ ((elm = $$(_.template(obj["" + what + "_template"])(obj["process_" + what](orig)))).orig = orig).better_version = elm;
69
66
  elm.better_select = obj;
70
67
  return elm;
71
68
  };
@@ -81,10 +78,10 @@
81
78
  option.select = function() {
82
79
  this.orig.selected = 'selected';
83
80
  this.setAttribute('class', 'option selected');
84
- if (bs.select.getAttribute('class').indexOf('open') !== -1) {
85
- bs.toggle();
81
+ bs.set_selected(option);
82
+ if (bs.open) {
83
+ return bs.toggle();
86
84
  }
87
- return bs.set_selected(option);
88
85
  };
89
86
  option.addEventListener('click', function() {
90
87
  return option.select();
@@ -96,6 +93,11 @@
96
93
  first_char = option.innerHTML.substr(0, 1).toLowerCase();
97
94
  if (!bs.options_by_first_char[first_char]) {
98
95
  bs.options_by_first_char[first_char] = [];
96
+ bs.options_by_first_char[first_char].sort = function() {
97
+ var sorted;
98
+ (sorted = _(this).sortBy('innerHTML')).unshift(0, this.length);
99
+ return this.splice.apply(this, sorted);
100
+ };
99
101
  }
100
102
  bs.options_by_first_char[first_char].push(option);
101
103
  bs.options_by_first_char[first_char].sort();
@@ -117,11 +119,12 @@
117
119
  BetterSelect = (function() {
118
120
 
119
121
  BetterSelect.prototype.defaults = {
120
- positionDropdown: true
122
+ positionDropdown: true,
123
+ resizeDropdown: true
121
124
  };
122
125
 
123
126
  function BetterSelect(elm, options) {
124
- var child, children, last_char, method, selected, _i, _len, _ref,
127
+ var child, children, method, selected, _i, _len, _ref,
125
128
  _this = this;
126
129
  if (!(elm && elm.tagName && elm.tagName === 'SELECT')) {
127
130
  return;
@@ -133,6 +136,7 @@
133
136
  selected = elm.selectedOptions;
134
137
  this.select = build_element('select', elm, this);
135
138
  _ref = this.select.children, this.selected_option = _ref[0], this.dropdown = _ref[1];
139
+ this.selected_option.better_select = this;
136
140
  if (elm.id) {
137
141
  this.select.id = "" + elm.id + "-better-select";
138
142
  this.dropdown.id = "" + elm.id + "-better-select-dropdown";
@@ -161,8 +165,14 @@
161
165
  this.default_selected[0].better_version.select();
162
166
  }
163
167
  this.selected_option.addEventListener('click', function() {
164
- _this.toggle();
165
- return _this.set_selected(_this.dropdown_selected_option);
168
+ if (_this.open) {
169
+ if (_this.focused_option) {
170
+ _this.focused_option.select();
171
+ }
172
+ } else {
173
+ _this.set_focused(_this.dropdown_selected_option);
174
+ }
175
+ return _this.toggle();
166
176
  });
167
177
  window.addEventListener('click', function(e) {
168
178
  if (!(e.target === _this.selected_option || e.target === _this.select || _this.options.indexOf(e.target) !== -1)) {
@@ -171,7 +181,7 @@
171
181
  }
172
182
  }
173
183
  });
174
- last_char = false;
184
+ this.last_char = false;
175
185
  this.selected_option.addEventListener('focus', function() {
176
186
  document.body.style.overflow = 'hidden';
177
187
  return addClass(_this.select, 'focus');
@@ -184,58 +194,18 @@
184
194
  }
185
195
  return true;
186
196
  });
187
- this.selected_option.addEventListener('keydown', function(e) {
197
+ this.selected_option.addEventListener('keyup', function(e) {
188
198
  if ([38, 40].indexOf(e.keyCode) !== -1) {
189
199
  return e.preventDefault();
190
200
  }
191
201
  });
192
- this.selected_option.addEventListener('keyup', function(e) {
193
- var char, keyCode, last_character, option;
194
- if (_this.open === false) {
195
- _this.toggle();
196
- }
197
- keyCode = e.keyCode;
198
- switch (keyCode) {
199
- case 38:
200
- _this.set_focused(_this.options[(_this.focus_index -= 1) < 0 ? _this.focus_index = _this.options.length - 1 : _this.focus_index]);
201
- break;
202
- case 40:
203
- _this.set_focused(_this.options[(_this.focus_index += 1) >= _this.options.length ? _this.focus_index = 0 : _this.focus_index]);
204
- break;
205
- case 13:
206
- _this.focused_option.select();
207
- break;
208
- default:
209
- if (keyCode > 47 && keyCode < 58) {
210
- char = numbers[keyCode - 47];
211
- } else if (keyCode > 64 && keyCode < 91) {
212
- char = letters[keyCode - 65];
213
- } else {
214
- if (_this.focused_option) {
215
- removeClass(_this.focused_option, 'focus');
216
- _this.focused_option = false;
217
- _this.focus_index = -1;
218
- }
219
- _this.toggle();
220
- }
221
- if (char && _this.options_by_first_char[char]) {
222
- if (last_char !== char) {
223
- _this.options_by_first_char[char].sort();
224
- }
225
- option = _this.options_by_first_char[char].shift();
226
- _this.options_by_first_char[char].push(option);
227
- _this.set_focused(option);
228
- _this.focus_index = _this.options.indexOf(option);
229
- last_character = char;
230
- }
202
+ this.selected_option.addEventListener('keydown', function(e) {
203
+ return _this.process_key_event(e);
204
+ });
205
+ window.addEventListener('keydown', function(e) {
206
+ if (_this.open) {
207
+ return _this.process_key_event(e);
231
208
  }
232
- _this.dropdown.addEventListener('click', function() {
233
- return console.log(arguments);
234
- });
235
- e.preventDefault();
236
- e.stopPropagation();
237
- e.returnValue = false;
238
- return false;
239
209
  });
240
210
  }
241
211
 
@@ -243,6 +213,61 @@
243
213
 
244
214
  BetterSelect.prototype.focus_index = -1;
245
215
 
216
+ BetterSelect.prototype.select_focused = function() {
217
+ if (this.focused_option) {
218
+ return this.focused_option.select();
219
+ }
220
+ };
221
+
222
+ BetterSelect.prototype.process_key_event = function(e) {
223
+ var char, isLetter, isNumber, keyCode, option;
224
+ keyCode = e.keyCode;
225
+ isNumber = keyCode > 47 && keyCode < 58;
226
+ isLetter = keyCode > 64 && keyCode < 91;
227
+ if (keyCode === 9 && this.open) {
228
+ return this.select_focused();
229
+ }
230
+ if (!([13, 38, 40].indexOf(keyCode) !== -1 || isLetter || isNumber)) {
231
+ return;
232
+ }
233
+ if ([13, 38, 40].indexOf(keyCode) !== -1 && this.open === false) {
234
+ this.toggle();
235
+ }
236
+ switch (keyCode) {
237
+ case 38:
238
+ this.set_focused(this.options[(this.focus_index -= 1) < 0 ? this.focus_index = this.options.length - 1 : this.focus_index]);
239
+ break;
240
+ case 40:
241
+ this.set_focused(this.options[(this.focus_index += 1) >= this.options.length ? this.focus_index = 0 : this.focus_index]);
242
+ break;
243
+ case 13:
244
+ this.select_focused();
245
+ break;
246
+ default:
247
+ if (isNumber) {
248
+ char = numbers[new String(keyCode - 48)];
249
+ } else if (isLetter) {
250
+ char = letters[keyCode - 65];
251
+ }
252
+ if (char && this.options_by_first_char[char]) {
253
+ if (!this.open) {
254
+ this.toggle();
255
+ }
256
+ if (this.last_char !== char) {
257
+ this.options_by_first_char[char].sort();
258
+ }
259
+ option = this.options_by_first_char[char].shift();
260
+ this.options_by_first_char[char].push(option);
261
+ this.set_focused(option);
262
+ this.focus_index = this.options.indexOf(option);
263
+ this.last_char = char;
264
+ }
265
+ }
266
+ e.preventDefault();
267
+ e.stopPropagation();
268
+ return e.returnValue = false;
269
+ };
270
+
246
271
  BetterSelect.prototype.set_focused = function(option) {
247
272
  var class_for_selected,
248
273
  _this = this;
@@ -258,7 +283,8 @@
258
283
  }
259
284
  this.focused_option = option;
260
285
  this.focused_option.setAttribute("class", "option focus" + (class_for_selected(option)));
261
- return this.focus_index = this.options.indexOf(this.focused_option);
286
+ this.focus_index = this.options.indexOf(this.focused_option);
287
+ return this.focused_option.scrollIntoView();
262
288
  };
263
289
 
264
290
  BetterSelect.prototype.open = false;
@@ -266,6 +292,9 @@
266
292
  BetterSelect.prototype.toggle = function() {
267
293
  var height, top;
268
294
  ((this.open = !this.open) ? addClass : removeClass)(this.select, 'open');
295
+ if (this.settings.resizeDropdown) {
296
+ this.dropdown.style.width = this.select.offsetWidth + 'px';
297
+ }
269
298
  if (this.settings.positionDropdown) {
270
299
  if (this.dropdown.offsetHeight > window.innerHeight) {
271
300
  height = window.innerHeight * .50;
@@ -279,8 +308,11 @@
279
308
  top = top || (getTop(this.select) - this.dropdown_selected_option.offsetTop);
280
309
  top = getTop(this.select) - (this.dropdown_selected_option.offsetTop - this.dropdown.scrollTop);
281
310
  this.dropdown.style.top = (top < 0 ? 0 : top) + 'px';
282
- return this.dropdown.style.left = this.open ? getLeft(this.select) + 'px' : '-9999px';
311
+ this.dropdown.style.left = this.open ? getLeft(this.select) + 'px' : '-9999px';
283
312
  }
313
+ return _(this.options_by_first_char).each(function(options) {
314
+ return options.sort();
315
+ });
284
316
  };
285
317
 
286
318
  BetterSelect.prototype.reset = function(option) {
@@ -299,15 +331,16 @@
299
331
  this.selected_option.innerHTML = option.innerHTML;
300
332
  e = document.createEvent('Event');
301
333
  e.initEvent('change', true, true);
302
- return this.select.orig.dispatchEvent(e);
334
+ this.select.orig.dispatchEvent(e);
303
335
  }
336
+ return this.selected_option.focus();
304
337
  };
305
338
 
306
339
  BetterSelect.prototype.option_template = '<div class="option"><%= innerHTML %></div>';
307
340
 
308
341
  BetterSelect.prototype.option_group_template = '<div class="optgroup"><div class="option-group-label"><%= label %></div></div>';
309
342
 
310
- BetterSelect.prototype.select_template = '<div class="select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>';
343
+ BetterSelect.prototype.select_template = '<div class="select better-select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>';
311
344
 
312
345
  BetterSelect.prototype.process_option = function(option) {
313
346
  return option;
@@ -20,12 +20,11 @@ setClasses = (tgt, classes) ->
20
20
  tgt
21
21
 
22
22
  addClass = (tgt, className) ->
23
- classes = getClasses tgt
24
- classes.push(className) if classes.indexOf(className) is -1
23
+ classes.push(className) if (classes = getClasses tgt).indexOf(className) is -1
25
24
  setClasses tgt, classes
26
25
 
27
26
  removeClass = (tgt, className) ->
28
- classes.splice(index, 1) unless index = (classes = getClasses tgt).indexOf className is -1
27
+ classes.splice(index, 1) unless (index = (classes = getClasses tgt).indexOf className) is -1
29
28
  setClasses tgt, classes
30
29
 
31
30
  letters = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'.split ' '
@@ -38,20 +37,30 @@ build_element = (what, orig, obj) ->
38
37
 
39
38
  renderOption = (orig_option, bs) ->
40
39
  option = build_element 'option', orig_option, bs
40
+
41
41
  option.reset = ->
42
42
  @orig.selected = undefined
43
43
  @setAttribute 'class', 'option'
44
44
  bs.reset @
45
+
45
46
  option.select = ->
46
47
  @orig.selected = 'selected'
47
48
  @setAttribute 'class', 'option selected'
48
- bs.toggle() if bs.select.getAttribute('class').indexOf('open') isnt -1
49
49
  bs.set_selected option
50
- option.addEventListener 'click', -> option.select()
50
+ bs.toggle() if bs.open
51
+
52
+ option.addEventListener 'click', ->
53
+ option.select()
54
+
51
55
  option.addEventListener 'mouseover', -> option.better_select.set_focused option
56
+
52
57
  bs.options.push option
53
58
  first_char = option.innerHTML.substr(0, 1).toLowerCase()
54
- bs.options_by_first_char[first_char] = [] unless bs.options_by_first_char[first_char]
59
+ unless bs.options_by_first_char[first_char]
60
+ bs.options_by_first_char[first_char] = []
61
+ bs.options_by_first_char[first_char].sort = ->
62
+ (sorted = _(@).sortBy 'innerHTML').unshift 0, @.length
63
+ @.splice.apply @, sorted
55
64
  bs.options_by_first_char[first_char].push option
56
65
  bs.options_by_first_char[first_char].sort()
57
66
  option
@@ -63,8 +72,11 @@ renderOptionGroup = (orig_group, bs) ->
63
72
  group
64
73
 
65
74
  class BetterSelect
75
+
66
76
  defaults:
67
77
  positionDropdown: true
78
+ resizeDropdown: true
79
+
68
80
  constructor: (elm, options) ->
69
81
  return unless elm && elm.tagName && elm.tagName is 'SELECT'
70
82
  @settings = _.extend {}, @defaults, options
@@ -74,17 +86,22 @@ class BetterSelect
74
86
  selected = elm.selectedOptions
75
87
  @select = build_element 'select', elm, @
76
88
  [@selected_option, @dropdown] = @select.children
89
+ @selected_option.better_select = @
90
+
77
91
  if elm.id
78
92
  @select.id = "#{elm.id}-better-select"
79
93
  @dropdown.id = "#{elm.id}-better-select-dropdown"
94
+
80
95
  @default_selected = [elm.children[elm.selectedIndex]]
81
96
  elm.parentNode.insertBefore @select, elm
82
97
  elm.parentNode.insertBefore elm, @select
83
98
  elm.style.display = 'none'
84
99
  children = elm.children
100
+
85
101
  if @settings.positionDropdown
86
102
  document.body.appendChild @dropdown
87
103
  @dropdown.style.left = '-9999px'
104
+
88
105
  for child in children
89
106
  switch child.tagName
90
107
  when 'OPTION'
@@ -92,65 +109,90 @@ class BetterSelect
92
109
  when 'OPTGROUP'
93
110
  method = renderOptionGroup
94
111
  @dropdown.appendChild(method child, @)
112
+
95
113
  @default_selected[0].better_version.select() if @default_selected
114
+
96
115
  @selected_option.addEventListener 'click', =>
116
+ if @open
117
+ @focused_option.select() if @focused_option
118
+ else
119
+ @set_focused @dropdown_selected_option
97
120
  @toggle()
98
- @set_selected @dropdown_selected_option
121
+
99
122
  window.addEventListener 'click', (e) =>
100
123
  unless e.target == @selected_option || e.target == @select || @options.indexOf(e.target) isnt -1
101
124
  @toggle() if @open
102
- last_char = false
125
+
126
+ @last_char = false
127
+
103
128
  @selected_option.addEventListener 'focus', =>
104
129
  document.body.style.overflow = 'hidden'
105
130
  addClass @select, 'focus'
131
+
106
132
  @selected_option.addEventListener 'blur', =>
107
133
  removeClass @select, 'focus'
108
134
  document.body.style.overflow = 'auto'
109
135
  @toggle() if @open is true
110
136
  true
111
- @selected_option.addEventListener 'keydown', (e) => e.preventDefault() unless [38, 40].indexOf(e.keyCode) is -1
112
- @selected_option.addEventListener 'keyup', (e) =>
113
- @toggle() if @open is false
114
- keyCode = e.keyCode
115
- switch keyCode
116
- when 38 then @set_focused @options[if (@focus_index -= 1) < 0 then @focus_index = @options.length - 1 else @focus_index]
117
- when 40 then @set_focused @options[if (@focus_index += 1) >= @options.length then @focus_index = 0 else @focus_index]
118
- when 13
119
- @focused_option.select()
120
- else
121
- if keyCode > 47 && keyCode < 58
122
- char = numbers[keyCode - 47]
123
- else if keyCode > 64 && keyCode < 91
124
- char = letters[keyCode - 65]
125
- else
126
- if @focused_option
127
- removeClass @focused_option, 'focus'
128
- @focused_option = false
129
- @focus_index = -1
130
- @toggle()
131
- if char && @options_by_first_char[char]
132
- @options_by_first_char[char].sort() unless last_char is char
133
- option = @options_by_first_char[char].shift()
134
- @options_by_first_char[char].push option
135
- @set_focused option
136
- @focus_index = @options.indexOf option
137
- last_character = char
138
- @dropdown.addEventListener('click', -> console.log arguments)
139
- e.preventDefault()
140
- e.stopPropagation()
141
- e.returnValue = false
142
- false
137
+
138
+ @selected_option.addEventListener 'keyup', (e) => e.preventDefault() unless [38, 40].indexOf(e.keyCode) is -1
139
+
140
+ @selected_option.addEventListener 'keydown', (e) => @process_key_event(e)
141
+
142
+ window.addEventListener 'keydown', (e) => @process_key_event(e) if @open
143
+
143
144
  focused_option: false
144
145
  focus_index: -1
146
+ select_focused: -> @focused_option.select() if @focused_option
147
+
148
+ process_key_event: (e) ->
149
+ keyCode = e.keyCode
150
+ isNumber = keyCode > 47 && keyCode < 58
151
+ isLetter = keyCode > 64 && keyCode < 91
152
+
153
+ return @select_focused() if keyCode is 9 && @open
154
+
155
+ return unless [13, 38, 40].indexOf(keyCode) isnt -1 || isLetter || isNumber
156
+
157
+ @toggle() if [13, 38, 40].indexOf(keyCode) isnt -1 && @open is false
158
+
159
+ switch keyCode
160
+ when 38 then @set_focused @options[if (@focus_index -= 1) < 0 then @focus_index = @options.length - 1 else @focus_index]
161
+ when 40 then @set_focused @options[if (@focus_index += 1) >= @options.length then @focus_index = 0 else @focus_index]
162
+ when 13 then @select_focused()
163
+ else
164
+ if isNumber
165
+ char = numbers[new String(keyCode - 48)]
166
+ else if isLetter
167
+ char = letters[keyCode - 65]
168
+
169
+ if char && @options_by_first_char[char]
170
+ @toggle() unless @open
171
+ @options_by_first_char[char].sort() unless @last_char is char
172
+ option = @options_by_first_char[char].shift()
173
+ @options_by_first_char[char].push option
174
+ @set_focused option
175
+ @focus_index = @options.indexOf option
176
+ @last_char = char
177
+
178
+ e.preventDefault()
179
+ e.stopPropagation()
180
+ e.returnValue = false
181
+
145
182
  set_focused: (option) ->
146
183
  class_for_selected = (option) => if @selected_option && option.innerHTML is @selected_option.innerHTML then " selected" else ""
147
184
  @focused_option.setAttribute('class', "option#{class_for_selected(@focused_option)}") if @focused_option
148
185
  @focused_option = option
149
186
  @focused_option.setAttribute("class", "option focus#{class_for_selected(option)}")
150
187
  @focus_index = @options.indexOf @focused_option
188
+ @focused_option.scrollIntoView()
189
+
151
190
  open: false
191
+
152
192
  toggle: ->
153
193
  (if @open = !@open then addClass else removeClass)(@select, 'open')
194
+ if @settings.resizeDropdown
195
+ @dropdown.style.width = @select.offsetWidth + 'px'
154
196
  if @settings.positionDropdown
155
197
  if @dropdown.offsetHeight > window.innerHeight
156
198
  height = window.innerHeight * .50
@@ -163,7 +205,10 @@ class BetterSelect
163
205
  top = getTop(@select) - (@dropdown_selected_option.offsetTop - @dropdown.scrollTop)
164
206
  @dropdown.style.top = (if top < 0 then 0 else top) + 'px'
165
207
  @dropdown.style.left = if @open then getLeft(@select) + 'px' else '-9999px'
208
+ _(@options_by_first_char).each (options) -> options.sort()
209
+
166
210
  reset: (option) -> @default_selected[0].better_version.select() if @default_selected
211
+
167
212
  set_selected: (option) ->
168
213
  unless @selected_option.innerHTML == option.innerHTML
169
214
  removeClass(@dropdown_selected_option, 'selected') if @dropdown_selected_option
@@ -172,12 +217,13 @@ class BetterSelect
172
217
  e = document.createEvent('Event')
173
218
  e.initEvent 'change', true, true
174
219
  @select.orig.dispatchEvent e
220
+ @selected_option.focus()
221
+
175
222
  option_template: '<div class="option"><%= innerHTML %></div>'
176
223
  option_group_template: '<div class="optgroup"><div class="option-group-label"><%= label %></div></div>'
177
- select_template: '<div class="select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>'
224
+ select_template: '<div class="select better-select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>'
178
225
  process_option: (option) -> option
179
226
  process_option_group: (option_group) -> option_group
180
227
  process_select: (select) -> select
181
228
 
182
-
183
229
  window.BetterSelect = BetterSelect