chosen-awesome-rails 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +104 -0
- data/LICENSE.txt +20 -0
- data/README.md +89 -0
- data/Rakefile +2 -0
- data/chosen-awesome-rails.gemspec +42 -0
- data/lib/chosen-awesome-rails.rb +13 -0
- data/lib/chosen-awesome-rails/engine.rb +7 -0
- data/lib/chosen-awesome-rails/engine3.rb +9 -0
- data/lib/chosen-awesome-rails/version.rb +5 -0
- data/vendor/assets/images/chosen-arrow.gif +0 -0
- data/vendor/assets/javascripts/chosen.js.coffee +39 -0
- data/vendor/assets/javascripts/chosen/chosen.js.coffee +470 -0
- data/vendor/assets/javascripts/chosen/multiple.js.coffee +136 -0
- data/vendor/assets/javascripts/chosen/parser.js.coffee +293 -0
- data/vendor/assets/javascripts/chosen/single.js.coffee +93 -0
- data/vendor/assets/stylesheets/chosen.css.scss +1 -0
- data/vendor/assets/stylesheets/chosen/bootstrap.css.scss +76 -0
- data/vendor/assets/stylesheets/chosen/default.css.scss +323 -0
- metadata +149 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
class Chosen.Multiple extends Chosen
|
4
|
+
constructor: ->
|
5
|
+
super
|
6
|
+
|
7
|
+
@pending_option = null
|
8
|
+
|
9
|
+
bind_option_events: (option) ->
|
10
|
+
option.$choice.find("a").unbind().
|
11
|
+
bind("mousedown", -> false).
|
12
|
+
bind("click", (evt) => @deselect_choice(evt))
|
13
|
+
return
|
14
|
+
|
15
|
+
set_default_value: ->
|
16
|
+
@$container.$search[0].value = ""
|
17
|
+
return
|
18
|
+
|
19
|
+
dropdown_mousedown: ->
|
20
|
+
@reset_pending_option()
|
21
|
+
super
|
22
|
+
return
|
23
|
+
|
24
|
+
keydown: (evt) ->
|
25
|
+
code = evt.which ? evt.keyCode
|
26
|
+
|
27
|
+
unless code is 8
|
28
|
+
@reset_pending_option()
|
29
|
+
|
30
|
+
switch code
|
31
|
+
when 8
|
32
|
+
@set_pending_option(true) if @pending_option
|
33
|
+
else
|
34
|
+
super
|
35
|
+
|
36
|
+
return
|
37
|
+
|
38
|
+
keyup: (evt) ->
|
39
|
+
code = evt.which ? evt.keyCode
|
40
|
+
|
41
|
+
if code is 8
|
42
|
+
@set_pending_option(false)
|
43
|
+
else
|
44
|
+
@reset_pending_option()
|
45
|
+
|
46
|
+
super
|
47
|
+
|
48
|
+
set_pending_option: (do_deselect) ->
|
49
|
+
if @pending_option and do_deselect
|
50
|
+
@deselect(@pending_option)
|
51
|
+
@reset_pending_option()
|
52
|
+
|
53
|
+
return if @get_caret_position() > 0 and @$container.$search[0].value.length
|
54
|
+
|
55
|
+
choise = @$container.$choices.find("li.chosen-option").last()[0]
|
56
|
+
option = @parser.find_by_element(choise)
|
57
|
+
return unless option
|
58
|
+
|
59
|
+
unless @pending_option
|
60
|
+
option.$choice.addClass("active")
|
61
|
+
@pending_option = option
|
62
|
+
|
63
|
+
return
|
64
|
+
|
65
|
+
reset_pending_option: ->
|
66
|
+
if @pending_option
|
67
|
+
@pending_option.$choice.removeClass("active")
|
68
|
+
@pending_option = null
|
69
|
+
|
70
|
+
return
|
71
|
+
|
72
|
+
deselect_choice: (evt) ->
|
73
|
+
option = @parser.find_by_element(evt.target.parentNode)
|
74
|
+
|
75
|
+
$choice = $(evt.target.parentNode)
|
76
|
+
$next = $choice.next("li.chosen-option")
|
77
|
+
$prev = $choice.prev("li.chosen-option")
|
78
|
+
$sibling = if $next.length then $next else if $prev.length then $prev else null
|
79
|
+
|
80
|
+
@deselect(option) if option
|
81
|
+
|
82
|
+
if $sibling and not @activated
|
83
|
+
$sibling.find("a").trigger("focus")
|
84
|
+
else
|
85
|
+
@activate()
|
86
|
+
|
87
|
+
evt.preventDefault()
|
88
|
+
evt.stopPropagation()
|
89
|
+
|
90
|
+
return @
|
91
|
+
|
92
|
+
deselect: (option) ->
|
93
|
+
@parser.deselect(option)
|
94
|
+
|
95
|
+
option.$choice.remove()
|
96
|
+
@update_dropdown_position()
|
97
|
+
|
98
|
+
@$target.trigger("change")
|
99
|
+
return @
|
100
|
+
|
101
|
+
select: (option) ->
|
102
|
+
return @ if not option or option.disabled or option.selected
|
103
|
+
|
104
|
+
@parser.select(option)
|
105
|
+
@$container.$search_container.before(option.$choice)
|
106
|
+
|
107
|
+
@$container.$search[0].value = ""
|
108
|
+
|
109
|
+
@bind_option_events(option)
|
110
|
+
@close()
|
111
|
+
|
112
|
+
@$target.trigger("change")
|
113
|
+
return @
|
114
|
+
|
115
|
+
deselect_all: ->
|
116
|
+
for option in @parser.selected()
|
117
|
+
@deselect(option)
|
118
|
+
|
119
|
+
return @
|
120
|
+
|
121
|
+
select_all: ->
|
122
|
+
for option in @parser.not_selected()
|
123
|
+
@select(option)
|
124
|
+
|
125
|
+
return @
|
126
|
+
|
127
|
+
load: ->
|
128
|
+
for option in @parser.selected()
|
129
|
+
@bind_option_events(option)
|
130
|
+
@$container.$search_container.before(option.$choice)
|
131
|
+
|
132
|
+
return @
|
133
|
+
|
134
|
+
@defaults:
|
135
|
+
is_multiple: true
|
136
|
+
placeholder: "Select some options"
|
@@ -0,0 +1,293 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
class Chosen.Parser
|
4
|
+
constructor: (@chosen)->
|
5
|
+
@all_options = []
|
6
|
+
@available_options = []
|
7
|
+
@selected_options = []
|
8
|
+
@selectable_options = []
|
9
|
+
|
10
|
+
@parse()
|
11
|
+
|
12
|
+
destroy: ->
|
13
|
+
delete @all_options
|
14
|
+
delete @available_options
|
15
|
+
delete @selected_options
|
16
|
+
delete @selectable_options
|
17
|
+
delete @chosen
|
18
|
+
return
|
19
|
+
|
20
|
+
parse: (selected_options = []) ->
|
21
|
+
formatter = @chosen.option_formatter || @default_formatter
|
22
|
+
current_group_label = null
|
23
|
+
group = null
|
24
|
+
|
25
|
+
@all_options = []
|
26
|
+
@selected_options = []
|
27
|
+
@selectable_options = []
|
28
|
+
|
29
|
+
$reset_link = @build_reset_link()
|
30
|
+
|
31
|
+
@chosen.$target.find("option").each (index, option) =>
|
32
|
+
if option.parentNode.nodeName is "OPTGROUP"
|
33
|
+
if current_group_label != option.parentNode.label
|
34
|
+
current_group_label = option.parentNode.label
|
35
|
+
group = $("<li />", class: "chosen-group", text: current_group_label)
|
36
|
+
else
|
37
|
+
group = null
|
38
|
+
|
39
|
+
classes = "chosen-option"
|
40
|
+
classes += " group" if group
|
41
|
+
classes += " selected" if option.selected
|
42
|
+
classes += " disabled" if option.disabled
|
43
|
+
|
44
|
+
$option = $(option)
|
45
|
+
selected = $.grep(selected_options, (o) => o.value is option.value and o.label is option.label)[0]
|
46
|
+
text = formatter($option)
|
47
|
+
|
48
|
+
option_obj =
|
49
|
+
$group: group
|
50
|
+
$listed: (selected and selected.$listed) or $("<li />", class: classes, html: text[0])
|
51
|
+
$choice: (selected and selected.$choice) or $("<li />", class: classes, html: [$reset_link.clone(), text[1]])
|
52
|
+
$option: (selected and selected.$option) or $option
|
53
|
+
blank: option.value is "" and index is 0
|
54
|
+
index: index
|
55
|
+
score: index * -1
|
56
|
+
label: option.text
|
57
|
+
value: option.value
|
58
|
+
selected: option.selected
|
59
|
+
disabled: option.disabled
|
60
|
+
match_type: null
|
61
|
+
|
62
|
+
@all_options.push option_obj
|
63
|
+
|
64
|
+
unless option_obj.blank
|
65
|
+
@selected_options.push option_obj if option.selected
|
66
|
+
@selectable_options.push option_obj unless option.selected
|
67
|
+
|
68
|
+
@order()
|
69
|
+
return @
|
70
|
+
|
71
|
+
update: (data) ->
|
72
|
+
parser = @chosen.option_parser || @default_parser
|
73
|
+
selected_options = []
|
74
|
+
|
75
|
+
for option in @all_options
|
76
|
+
if option.selected or option.blank
|
77
|
+
selected_options.push(option)
|
78
|
+
else
|
79
|
+
option.$option.remove()
|
80
|
+
|
81
|
+
for attrs in data
|
82
|
+
parsed = parser(attrs)
|
83
|
+
unless $.grep(selected_options, (o) => o.value is parsed.value.toString() and o.label == parsed.text.toString() ).length
|
84
|
+
@chosen.$target.append($("<option />", parsed))
|
85
|
+
|
86
|
+
@parse(selected_options)
|
87
|
+
return @
|
88
|
+
|
89
|
+
insert: (data) ->
|
90
|
+
formatter = @chosen.option_formatter || @default_formatter
|
91
|
+
classes = "chosen-option"
|
92
|
+
$option = $("<option />", value: data.value, text: data.label)
|
93
|
+
$reset_link = @build_reset_link()
|
94
|
+
text = formatter($option)
|
95
|
+
|
96
|
+
@chosen.$target.append($option)
|
97
|
+
|
98
|
+
option_obj =
|
99
|
+
$group: null
|
100
|
+
$listed: $("<li />", class: classes, html: text[0])
|
101
|
+
$choice: $("<li />", class: classes, html: [$reset_link, text[1]])
|
102
|
+
$option: $option
|
103
|
+
blank: false
|
104
|
+
index: 0
|
105
|
+
score: 0
|
106
|
+
label: $option[0].text
|
107
|
+
value: $option[0].value
|
108
|
+
selected: false
|
109
|
+
disabled: false
|
110
|
+
match_type: 0
|
111
|
+
|
112
|
+
@all_options.unshift option_obj
|
113
|
+
@available_options.unshift option_obj
|
114
|
+
@selectable_options.unshift option_obj
|
115
|
+
|
116
|
+
option_obj
|
117
|
+
|
118
|
+
restore: (option) ->
|
119
|
+
@select(option)
|
120
|
+
|
121
|
+
unless $.grep(@all_options, (o) => option.label is o.label).length
|
122
|
+
@chosen.$target.append(option.$option)
|
123
|
+
|
124
|
+
@all_options.unshift option
|
125
|
+
@available_options.unshift option
|
126
|
+
@selectable_options.unshift option
|
127
|
+
|
128
|
+
@parse()
|
129
|
+
|
130
|
+
remove: (option) ->
|
131
|
+
return if option.selected
|
132
|
+
|
133
|
+
option.$listed.remove()
|
134
|
+
option.$choice.remove()
|
135
|
+
option.$option.remove()
|
136
|
+
|
137
|
+
for collection in [@all_options, @available_options, @selected_options, @selectable_options]
|
138
|
+
index = collection.indexOf(option)
|
139
|
+
collection.splice(index, 1) if index > -1
|
140
|
+
|
141
|
+
to_html: ->
|
142
|
+
last_group = null
|
143
|
+
list = []
|
144
|
+
|
145
|
+
for option in @available_options
|
146
|
+
if option.$group
|
147
|
+
if not last_group or (last_group and last_group.text() isnt option.$group.text())
|
148
|
+
last_group = option.$group.clone()
|
149
|
+
list.push last_group
|
150
|
+
else
|
151
|
+
last_group = null
|
152
|
+
|
153
|
+
list.push option.$listed
|
154
|
+
|
155
|
+
list
|
156
|
+
|
157
|
+
find_by_element: (element) ->
|
158
|
+
for option in @all_options
|
159
|
+
if option.$listed[0] is element or option.$choice[0] is element
|
160
|
+
return option
|
161
|
+
|
162
|
+
return null
|
163
|
+
|
164
|
+
index_of: (option) ->
|
165
|
+
if option then @available_options.indexOf(option) else 0
|
166
|
+
|
167
|
+
select: (option) ->
|
168
|
+
return @ unless option
|
169
|
+
|
170
|
+
option.$option.prop(selected: true)
|
171
|
+
option.$listed.addClass("selected")
|
172
|
+
option.$choice.addClass("selected")
|
173
|
+
option.selected = true
|
174
|
+
|
175
|
+
index = @selectable_options.indexOf(option)
|
176
|
+
@selectable_options.splice(index, 1) unless index is -1
|
177
|
+
@selected_options.push(option)
|
178
|
+
|
179
|
+
return @
|
180
|
+
|
181
|
+
deselect: (option) ->
|
182
|
+
return @ unless option
|
183
|
+
|
184
|
+
option.$option.prop(selected: false)
|
185
|
+
option.$listed.removeClass("selected")
|
186
|
+
option.$choice.removeClass("selected")
|
187
|
+
option.selected = false
|
188
|
+
|
189
|
+
index = @selected_options.indexOf(option)
|
190
|
+
@selected_options.splice(index, 1) unless index is -1
|
191
|
+
@selectable_options.push(option)
|
192
|
+
|
193
|
+
return @
|
194
|
+
|
195
|
+
selected: ->
|
196
|
+
$.grep @available_options, (option) ->
|
197
|
+
option.selected
|
198
|
+
|
199
|
+
not_selected: ->
|
200
|
+
$.grep @available_options, (option) ->
|
201
|
+
not option.selected
|
202
|
+
|
203
|
+
exact_matches: ->
|
204
|
+
$.grep @available_options, (option) ->
|
205
|
+
option.match_type is 0
|
206
|
+
|
207
|
+
includes_blank: ->
|
208
|
+
not not @blank_option()
|
209
|
+
|
210
|
+
blank_option: ->
|
211
|
+
for option in @all_options
|
212
|
+
return option if option.blank
|
213
|
+
|
214
|
+
return null
|
215
|
+
|
216
|
+
apply_filter: (value) ->
|
217
|
+
@reset_filter()
|
218
|
+
|
219
|
+
if (value = $.trim(value))
|
220
|
+
scores = [
|
221
|
+
@all_options.length * 12, @all_options.length * 9
|
222
|
+
@all_options.length * 6, @all_options.length * 3
|
223
|
+
@all_options.length
|
224
|
+
]
|
225
|
+
|
226
|
+
exact_query = value.toLowerCase()
|
227
|
+
query = exact_query.replace(Parser.escape_exp, "\\$&").split(" ")
|
228
|
+
|
229
|
+
expressions_collection = $.map(query, (word, index) ->
|
230
|
+
return [[
|
231
|
+
new RegExp("^#{word}$", "i"), new RegExp("^#{word}", "i")
|
232
|
+
new RegExp("#{word}$", "i"), new RegExp(word, "i")
|
233
|
+
]]
|
234
|
+
)
|
235
|
+
|
236
|
+
for option in @all_options
|
237
|
+
if option.label.toLowerCase() is exact_query
|
238
|
+
option.match_type = 0
|
239
|
+
else
|
240
|
+
option.match_type = null
|
241
|
+
|
242
|
+
words = option.label.split(" ")
|
243
|
+
|
244
|
+
for word in words
|
245
|
+
for expressions in expressions_collection
|
246
|
+
for expression, index in expressions
|
247
|
+
if word.match(expression)
|
248
|
+
if option.match_type is null
|
249
|
+
option.match_type = index + 1
|
250
|
+
|
251
|
+
option.score += scores[option.match_type]
|
252
|
+
break
|
253
|
+
else if index is expressions.length - 1
|
254
|
+
option.score -= 1
|
255
|
+
|
256
|
+
@order()
|
257
|
+
return @
|
258
|
+
|
259
|
+
reset_filter: ->
|
260
|
+
option.score = option.index * -1 for option in @all_options
|
261
|
+
return @
|
262
|
+
|
263
|
+
order: ->
|
264
|
+
@all_options = @all_options.sort (a, b) ->
|
265
|
+
if a.score > b.score then -1 else if a.score < b.score then 1 else 0
|
266
|
+
|
267
|
+
@available_options = []
|
268
|
+
|
269
|
+
for option in @all_options
|
270
|
+
if not option.blank
|
271
|
+
@available_options.push(option)
|
272
|
+
|
273
|
+
return @
|
274
|
+
|
275
|
+
default_parser: (attrs) ->
|
276
|
+
value: attrs.value
|
277
|
+
text: attrs.label
|
278
|
+
data: { source: attrs }
|
279
|
+
|
280
|
+
default_formatter: ($option) ->
|
281
|
+
value = $option.contents().text()
|
282
|
+
[value, value]
|
283
|
+
|
284
|
+
build_reset_link: ->
|
285
|
+
$("<a />",
|
286
|
+
text: "×"
|
287
|
+
href: "javascript:void(0)"
|
288
|
+
class: "chosen-delete"
|
289
|
+
tabindex: @chosen.$target[0].tabindex || "0"
|
290
|
+
)
|
291
|
+
|
292
|
+
|
293
|
+
@escape_exp: /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g
|
@@ -0,0 +1,93 @@
|
|
1
|
+
$ = jQuery
|
2
|
+
|
3
|
+
class Chosen.Single extends Chosen
|
4
|
+
build: ->
|
5
|
+
super
|
6
|
+
|
7
|
+
if @allow_deselect
|
8
|
+
@$container.$reset = @parser.build_reset_link()
|
9
|
+
@$container.append(@$container.$reset)
|
10
|
+
|
11
|
+
return
|
12
|
+
|
13
|
+
bind_events: ->
|
14
|
+
super
|
15
|
+
|
16
|
+
if @allow_deselect
|
17
|
+
@$container.$reset.bind "mousedown", (evt) ->
|
18
|
+
evt.stopImmediatePropagation()
|
19
|
+
evt.preventDefault()
|
20
|
+
|
21
|
+
@$container.$reset.bind "click", (evt) =>
|
22
|
+
@deselect()
|
23
|
+
@load()
|
24
|
+
@activate()
|
25
|
+
evt.stopImmediatePropagation()
|
26
|
+
|
27
|
+
return
|
28
|
+
|
29
|
+
unbind_events: ->
|
30
|
+
super
|
31
|
+
|
32
|
+
if @allow_deselect
|
33
|
+
@$container.$reset.unbind()
|
34
|
+
|
35
|
+
return
|
36
|
+
|
37
|
+
open: ->
|
38
|
+
return @ if @opened
|
39
|
+
|
40
|
+
selected = @parser.selected()[0]
|
41
|
+
|
42
|
+
if selected and @$container.$search[0].value is selected.label
|
43
|
+
@$container.$search[0].value = ""
|
44
|
+
|
45
|
+
super
|
46
|
+
|
47
|
+
set_default_value: ->
|
48
|
+
selected = @parser.selected()[0]
|
49
|
+
@$container.$search[0].value = if selected then selected.label else ""
|
50
|
+
@$container.$search[0].defaultValue = @$container.$search[0].value
|
51
|
+
|
52
|
+
if selected and not selected.blank
|
53
|
+
@$container.removeClass("placeholder")
|
54
|
+
else
|
55
|
+
@$container.addClass("placeholder")
|
56
|
+
|
57
|
+
return
|
58
|
+
|
59
|
+
deselect: (option) ->
|
60
|
+
@parser.deselect(option || @parser.selected()[0])
|
61
|
+
|
62
|
+
@set_default_value()
|
63
|
+
@close()
|
64
|
+
|
65
|
+
@$target.trigger("change")
|
66
|
+
return @
|
67
|
+
|
68
|
+
select: (option) ->
|
69
|
+
return @ if not option or option.disabled or option.selected
|
70
|
+
|
71
|
+
@parser.deselect(@parser.selected()[0])
|
72
|
+
@parser.select(option)
|
73
|
+
|
74
|
+
@set_default_value()
|
75
|
+
@close()
|
76
|
+
|
77
|
+
@$target.trigger("change")
|
78
|
+
return @
|
79
|
+
|
80
|
+
deselect_all: ->
|
81
|
+
@deselect()
|
82
|
+
return @
|
83
|
+
|
84
|
+
select_all: ->
|
85
|
+
return @
|
86
|
+
|
87
|
+
load: ->
|
88
|
+
@set_default_value()
|
89
|
+
return @
|
90
|
+
|
91
|
+
@defaults:
|
92
|
+
is_multiple: false
|
93
|
+
placeholder: "Select an option"
|