better_select 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,10 +8,10 @@ Gem::Specification.new do |gem|
8
8
  gem.summary = "A better HTMLSelectElement replacement, for Rails"
9
9
  gem.homepage = "http://www.benjaminbergstein.com"
10
10
 
11
- gem.files = `git ls-files`.split($\) + ['vendor/javascripts', 'vendor/stylesheets']
12
11
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
13
  gem.name = "better_select"
15
14
  gem.require_paths = ["lib", "vendor"]
15
+ gem.files = `git ls-files`.split($\) + ['vendor/javascripts/better-select.js.coffee', 'vendor/stylesheets/better-select.css.scss']
16
16
  gem.version = BetterSelect::VERSION
17
17
  end
@@ -1,3 +1,3 @@
1
1
  module BetterSelect
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,185 @@
1
+ $$ = (html) ->
2
+ elm = document.createElement 'div'
3
+ elm.innerHTML = html
4
+ if elm.children.length > 1 then elm.children else elm.children[0]
5
+
6
+ getPos = (tgt, method) ->
7
+ pos = 0
8
+ while tgt
9
+ pos += tgt[method]
10
+ tgt = tgt.offsetParent
11
+ pos
12
+
13
+ getTop = (tgt) -> getPos tgt, 'offsetTop'
14
+ getLeft = (tgt) -> getPos tgt, 'offsetLeft'
15
+
16
+ getClasses = (tgt) -> tgt.getAttribute('class').split ' '
17
+
18
+ setClasses = (tgt, classes) ->
19
+ tgt.setAttribute 'class', classes.join ' '
20
+ tgt
21
+
22
+ addClass = (tgt, className) ->
23
+ classes = getClasses tgt
24
+ classes.push(className) if classes.indexOf(className) is -1
25
+ setClasses tgt, classes
26
+
27
+ removeClass = (tgt, className) ->
28
+ classes.splice(index, 1) unless index = (classes = getClasses tgt).indexOf className is -1
29
+ setClasses tgt, classes
30
+
31
+ 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 ' '
32
+ numbers = '0 1 2 3 4 5 6 7 8 9 0'.split ' '
33
+
34
+ build_element = (what, orig, obj) ->
35
+ elm = $$ _.template(obj["#{what}_template"]) obj["process_#{what}"] orig
36
+ elm.orig = orig
37
+ orig.better_version = elm
38
+ elm.better_select = obj
39
+ elm
40
+
41
+ renderOption = (orig_option, bs) ->
42
+ option = build_element 'option', orig_option, bs
43
+ option.reset = ->
44
+ @orig.selected = undefined
45
+ @setAttribute 'class', 'option'
46
+ bs.reset @
47
+ option.select = ->
48
+ @orig.selected = 'selected'
49
+ @setAttribute 'class', 'option selected'
50
+ bs.toggle() if bs.select.getAttribute('class').indexOf('open') isnt -1
51
+ bs.set_selected option
52
+ option.addEventListener 'click', -> option.select()
53
+ option.addEventListener 'mouseover', -> option.better_select.set_focused option
54
+ bs.options.push option
55
+ first_char = option.innerHTML.substr(0, 1).toLowerCase()
56
+ bs.options_by_first_char[first_char] = [] unless bs.options_by_first_char[first_char]
57
+ bs.options_by_first_char[first_char].push option
58
+ bs.options_by_first_char[first_char].sort()
59
+ option
60
+
61
+ renderOptionGroup = (orig_group, bs) ->
62
+ group = build_element 'option_group', orig_group, bs
63
+ group.appendChild(renderOption child, bs) for child in orig_group.children
64
+ bs.option_groups.push group
65
+ group
66
+
67
+ class BetterSelect
68
+ defaults:
69
+ positionDropdown: true
70
+ constructor: (elm, options) ->
71
+ return unless elm && elm.tagName && elm.tagName is 'SELECT'
72
+ @settings = _.extend {}, @defaults, options
73
+ @options = []
74
+ @options_by_first_char = {}
75
+ @option_groups = []
76
+ selected = elm.selectedOptions
77
+ @select = build_element 'select', elm, @
78
+ [@selected_option, @dropdown] = @select.children
79
+ if elm.id
80
+ @select.id = "#{elm.id}-better-select"
81
+ @dropdown.id = "#{elm.id}-better-select-dropdown"
82
+ @default_selected = [elm.children[elm.selectedIndex]]
83
+ elm.parentNode.insertBefore @select, elm
84
+ elm.parentNode.insertBefore elm, @select
85
+ elm.style.display = 'none'
86
+ children = elm.children
87
+ if @settings.positionDropdown
88
+ document.body.appendChild @dropdown
89
+ @dropdown.style.left = '-9999px'
90
+ for child in children
91
+ switch child.tagName
92
+ when 'OPTION'
93
+ method = renderOption
94
+ when 'OPTGROUP'
95
+ method = renderOptionGroup
96
+ @dropdown.appendChild(method child, @)
97
+ @default_selected[0].better_version.select() if @default_selected
98
+ @selected_option.addEventListener 'click', =>
99
+ @toggle()
100
+ @set_selected @dropdown_selected_option
101
+ window.addEventListener 'click', (e) =>
102
+ unless e.target == @selected_option || e.target == @select || @options.indexOf(e.target) isnt -1
103
+ @toggle() if @open
104
+ last_char = false
105
+ @selected_option.addEventListener 'focus', =>
106
+ document.body.style.overflow = 'hidden'
107
+ addClass @select, 'focus'
108
+ @selected_option.addEventListener 'blur', =>
109
+ removeClass @select, 'focus'
110
+ document.body.style.overflow = 'auto'
111
+ @toggle() if @open is true
112
+ true
113
+ @selected_option.addEventListener 'keydown', (e) => e.preventDefault() unless [38, 40].indexOf(e.keyCode) is -1
114
+ @selected_option.addEventListener 'keyup', (e) =>
115
+ @toggle() if @open is false
116
+ keyCode = e.keyCode
117
+ switch keyCode
118
+ when 38 then @set_focused @options[if (@focus_index -= 1) < 0 then @focus_index = @options.length - 1 else @focus_index]
119
+ when 40 then @set_focused @options[if (@focus_index += 1) >= @options.length then @focus_index = 0 else @focus_index]
120
+ when 13
121
+ @focused_option.select()
122
+ else
123
+ if keyCode > 47 && keyCode < 58
124
+ char = numbers[keyCode - 47]
125
+ else if keyCode > 64 && keyCode < 91
126
+ char = letters[keyCode - 65]
127
+ else
128
+ if @focused_option
129
+ removeClass @focused_option, 'focus'
130
+ @focused_option = false
131
+ @focus_index = -1
132
+ @toggle()
133
+ if char && @options_by_first_char[char]
134
+ @options_by_first_char[char].sort() unless last_char is char
135
+ option = @options_by_first_char[char].shift()
136
+ @options_by_first_char[char].push option
137
+ @set_focused option
138
+ @focus_index = @options.indexOf option
139
+ last_character = char
140
+ @dropdown.addEventListener('click', -> console.log arguments)
141
+ e.preventDefault()
142
+ e.stopPropagation()
143
+ e.returnValue = false
144
+ false
145
+ focused_option: false
146
+ focus_index: -1
147
+ set_focused: (option) ->
148
+ class_for_selected = (option) => if @selected_option && option.innerHTML is @selected_option.innerHTML then " selected" else ""
149
+ @focused_option.setAttribute('class', "option#{class_for_selected(@focused_option)}") if @focused_option
150
+ @focused_option = option
151
+ @focused_option.setAttribute("class", "option focus#{class_for_selected(option)}")
152
+ @focus_index = @options.indexOf @focused_option
153
+ open: false
154
+ toggle: ->
155
+ (if @open = !@open then addClass else removeClass)(@select, 'open')
156
+ if @settings.positionDropdown
157
+ if @dropdown.offsetHeight > window.innerHeight
158
+ height = window.innerHeight * .50
159
+ @dropdown.style.height = height + 'px'
160
+ @dropdown.style['overflow-y'] = 'auto'
161
+ if @dropdown_selected_option.offsetTop > height || @adjust_height
162
+ @dropdown_selected_option.scrollIntoView()
163
+ @adjust_height = true
164
+ top = top || (getTop(@select) - @dropdown_selected_option.offsetTop)
165
+ top = getTop(@select) - (@dropdown_selected_option.offsetTop - @dropdown.scrollTop)
166
+ @dropdown.style.top = (if top < 0 then 0 else top) + 'px'
167
+ @dropdown.style.left = if @open then getLeft(@select) + 'px' else '-9999px'
168
+ reset: (option) -> @default_selected[0].better_version.select() if @default_selected
169
+ set_selected: (option) ->
170
+ unless @selected_option.innerHTML == option.innerHTML
171
+ removeClass(@dropdown_selected_option, 'selected') if @dropdown_selected_option
172
+ addClass @dropdown_selected_option = option, 'selected'
173
+ @selected_option.innerHTML = option.innerHTML
174
+ e = document.createEvent('Event')
175
+ e.initEvent 'change', true, true
176
+ @select.orig.dispatchEvent e
177
+ option_template: '<div class="option"><%= innerHTML %></div>'
178
+ option_group_template: '<div class="optgroup"><div class="option-group-label"><%= label %></div></div>'
179
+ select_template: '<div class="select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>'
180
+ process_option: (option) -> option
181
+ process_option_group: (option_group) -> option_group
182
+ process_select: (select) -> select
183
+
184
+
185
+ window.BetterSelect = BetterSelect
@@ -0,0 +1,32 @@
1
+ .better-select-dropdown {
2
+ position: fixed;
3
+
4
+ .option {
5
+ cursor: pointer;
6
+ }
7
+ }
8
+
9
+ .select {
10
+ position: static;
11
+
12
+ &.dont-position-dropdown {
13
+ position: relative;
14
+
15
+ .dropdown {
16
+ top: 100%;
17
+ left: -99999px;
18
+ }
19
+ }
20
+
21
+ &.open {
22
+ &.dont-position-dropdown {
23
+ .dropdown {
24
+ left: 0px;
25
+ }
26
+ }
27
+ }
28
+
29
+ .selected-option {
30
+ cursor: pointer;
31
+ }
32
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_select
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -28,6 +28,8 @@ files:
28
28
  - lib/better_select.rb
29
29
  - lib/better_select/engine.rb
30
30
  - lib/better_select/version.rb
31
+ - vendor/javascripts/better-select.js.coffee
32
+ - vendor/stylesheets/better-select.css.scss
31
33
  homepage: http://www.benjaminbergstein.com
32
34
  licenses: []
33
35
  post_install_message: