Skip to content

Commit f301b10

Browse files
committed
Merge branch 'master' into add_all_options
2 parents c409235 + 2af0fb0 commit f301b10

File tree

7 files changed

+119
-40
lines changed

7 files changed

+119
-40
lines changed

chosen.jquery.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "chosen",
33
"description": "Chosen is a JavaScript plugin that makes long, unwieldy select boxes much more user-friendly. It is currently available in both jQuery and Prototype flavors.",
4-
"version": "0.13.0",
4+
"version": "0.14.0",
55
"licenses": [
66
{
77
"type": "MIT",

coffee/chosen.jquery.coffee

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ $.fn.extend({
55
# Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
66
# Continue on if running IE document type but in compatibility mode
77
return this unless AbstractChosen.browser_is_supported()
8-
this.each((input_field) ->
8+
this.each (input_field) ->
99
$this = $ this
10-
$this.data('chosen', new Chosen(this, options)) unless $this.hasClass "chzn-done"
11-
)
10+
chosen = $this.data('chosen')
11+
if options is 'destroy' && chosen
12+
chosen.destroy()
13+
else unless chosen
14+
$this.data('chosen', new Chosen(this, options))
15+
16+
return
17+
1218
})
1319

1420
class Chosen extends AbstractChosen
@@ -65,41 +71,50 @@ class Chosen extends AbstractChosen
6571
@form_field_jq.trigger("liszt:ready", {chosen: this})
6672

6773
register_observers: ->
68-
@container.mousedown (evt) => this.container_mousedown(evt); return
69-
@container.mouseup (evt) => this.container_mouseup(evt); return
70-
@container.mouseenter (evt) => this.mouse_enter(evt); return
71-
@container.mouseleave (evt) => this.mouse_leave(evt); return
74+
@container.bind 'mousedown.chosen', (evt) => this.container_mousedown(evt); return
75+
@container.bind 'mouseup.chosen', (evt) => this.container_mouseup(evt); return
76+
@container.bind 'mouseenter.chosen', (evt) => this.mouse_enter(evt); return
77+
@container.bind 'mouseleave.chosen', (evt) => this.mouse_leave(evt); return
7278

73-
@search_results.mouseup (evt) => this.search_results_mouseup(evt); return
74-
@search_results.mouseover (evt) => this.search_results_mouseover(evt); return
75-
@search_results.mouseout (evt) => this.search_results_mouseout(evt); return
76-
@search_results.bind 'mousewheel DOMMouseScroll', (evt) => this.search_results_mousewheel(evt); return
79+
@search_results.bind 'mouseup.chosen', (evt) => this.search_results_mouseup(evt); return
80+
@search_results.bind 'mouseover.chosen', (evt) => this.search_results_mouseover(evt); return
81+
@search_results.bind 'mouseout.chosen', (evt) => this.search_results_mouseout(evt); return
82+
@search_results.bind 'mousewheel.chosen DOMMouseScroll.chosen', (evt) => this.search_results_mousewheel(evt); return
7783

78-
@form_field_jq.bind "liszt:updated", (evt) => this.results_update_field(evt); return
79-
@form_field_jq.bind "liszt:activate", (evt) => this.activate_field(evt); return
80-
@form_field_jq.bind "liszt:open", (evt) => this.container_mousedown(evt); return
84+
@form_field_jq.bind "liszt:updated.chosen", (evt) => this.results_update_field(evt); return
85+
@form_field_jq.bind "liszt:activate.chosen", (evt) => this.activate_field(evt); return
86+
@form_field_jq.bind "liszt:open.chosen", (evt) => this.container_mousedown(evt); return
8187

82-
@search_field.blur (evt) => this.input_blur(evt); return
83-
@search_field.keyup (evt) => this.keyup_checker(evt); return
84-
@search_field.keydown (evt) => this.keydown_checker(evt); return
85-
@search_field.focus (evt) => this.input_focus(evt); return
88+
@search_field.bind 'blur.chosen', (evt) => this.input_blur(evt); return
89+
@search_field.bind 'keyup.chosen', (evt) => this.keyup_checker(evt); return
90+
@search_field.bind 'keydown.chosen', (evt) => this.keydown_checker(evt); return
91+
@search_field.bind 'focus.chosen', (evt) => this.input_focus(evt); return
8692

8793
if @is_multiple
88-
@search_choices.click (evt) => this.choices_click(evt); return
94+
@search_choices.bind 'click.chosen', (evt) => this.choices_click(evt); return
8995
else
90-
@container.click (evt) => evt.preventDefault(); return # gobble click of anchor
96+
@container.bind 'click.chosen', (evt) -> evt.preventDefault(); return # gobble click of anchor
97+
98+
destroy: ->
99+
$(document).unbind "click.chosen", @click_test_action
100+
if @search_field[0].tabIndex
101+
@form_field_jq[0].tabIndex = @search_field[0].tabIndex
102+
103+
@container.remove()
104+
@form_field_jq.removeData('chosen')
105+
@form_field_jq.show()
91106

92107
search_field_disabled: ->
93108
@is_disabled = @form_field_jq[0].disabled
94109
if(@is_disabled)
95110
@container.addClass 'chzn-disabled'
96111
@search_field[0].disabled = true
97-
@selected_item.unbind "focus", @activate_action if !@is_multiple
112+
@selected_item.unbind "focus.chosen", @activate_action if !@is_multiple
98113
this.close_field()
99114
else
100115
@container.removeClass 'chzn-disabled'
101116
@search_field[0].disabled = false
102-
@selected_item.bind "focus", @activate_action if !@is_multiple
117+
@selected_item.bind "focus.chosen", @activate_action if !@is_multiple
103118

104119
container_mousedown: (evt) ->
105120
if !@is_disabled
@@ -109,7 +124,7 @@ class Chosen extends AbstractChosen
109124
if not (evt? and ($ evt.target).hasClass "search-choice-close")
110125
if not @active_field
111126
@search_field.val "" if @is_multiple
112-
$(document).click @click_test_action
127+
$(document).bind 'click.chosen', @click_test_action
113128
this.results_show()
114129
else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chzn-single").length)
115130
evt.preventDefault()
@@ -131,7 +146,7 @@ class Chosen extends AbstractChosen
131146
this.close_field() if not @active_field and @container.hasClass "chzn-container-active"
132147

133148
close_field: ->
134-
$(document).unbind "click", @click_test_action
149+
$(document).unbind "click.chosen", @click_test_action
135150

136151
@active_field = false
137152
this.results_hide()
@@ -274,7 +289,7 @@ class Chosen extends AbstractChosen
274289
@form_field_label = $("label[for='#{@form_field.id}']") #next check for a for=#{id}
275290

276291
if @form_field_label.length > 0
277-
@form_field_label.click (evt) => if @is_multiple then this.container_mousedown(evt) else this.activate_field()
292+
@form_field_label.bind 'click.chosen', (evt) => if @is_multiple then this.container_mousedown(evt) else this.activate_field()
278293

279294
show_search_field_default: ->
280295
if @is_multiple and this.choices_count() < 1 and not @active_field
@@ -305,7 +320,7 @@ class Chosen extends AbstractChosen
305320
choice.addClass 'search-choice-disabled'
306321
else
307322
close_link = $('<a />', { class: 'search-choice-close', 'data-option-array-index': item.array_index })
308-
close_link.click (evt) => this.choice_destroy_link_click(evt)
323+
close_link.bind 'click.chosen', (evt) => this.choice_destroy_link_click(evt)
309324
choice.append close_link
310325

311326
@search_container.before choice

coffee/chosen.proto.coffee

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ class @Chosen extends AbstractChosen
8080
else
8181
@container.observe "click", (evt) => evt.preventDefault() # gobble click of anchor
8282

83+
destroy: ->
84+
document.stopObserving "click", @click_test_action
85+
86+
@form_field.stopObserving()
87+
@container.stopObserving()
88+
@search_results.stopObserving()
89+
@search_field.stopObserving()
90+
@form_field_label.stopObserving() if @form_field_label?
91+
92+
if @is_multiple
93+
@search_choices.stopObserving()
94+
@container.select(".search-choice-close").each (choice) ->
95+
choice.stopObserving()
96+
else
97+
@selected_item.stopObserving()
98+
99+
if @search_field.tabIndex
100+
@form_field.tabIndex = @search_field.tabIndex
101+
102+
@container.remove()
103+
@form_field.show()
104+
83105
search_field_disabled: ->
84106
@is_disabled = @form_field.disabled
85107
if(@is_disabled)

coffee/lib/abstract-chosen.coffee

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class AbstractChosen
3434
@single_backstroke_delete = if @options.single_backstroke_delete? then @options.single_backstroke_delete else true
3535
@max_selected_options = @options.max_selected_options || Infinity
3636
@inherit_select_classes = @options.inherit_select_classes || false
37+
@display_selected_options = if @options.display_selected_options? then @options.display_selected_options else true
38+
@display_disabled_options = if @options.display_disabled_options? then @options.display_disabled_options else true
3739

3840
set_default_text: ->
3941
if @form_field.getAttribute("data-placeholder")
@@ -62,9 +64,9 @@ class AbstractChosen
6264
results_option_build: (options) ->
6365
content = ''
6466
for data in @results_data
65-
if data.group && (data.search_match || data.group_match)
67+
if data.group
6668
content += this.result_add_group data
67-
else if !data.empty && data.search_match
69+
else
6870
content += this.result_add_option data
6971

7072
# this select logic pins on an awkward flag
@@ -78,6 +80,9 @@ class AbstractChosen
7880
content
7981

8082
result_add_option: (option) ->
83+
return '' unless option.search_match
84+
return '' unless this.include_option_in_results(option)
85+
8186
classes = []
8287
classes.push "active-result" if !option.disabled and !(option.selected and @is_multiple)
8388
classes.push "disabled-result" if option.disabled and !(option.selected and @is_multiple)
@@ -90,6 +95,9 @@ class AbstractChosen
9095
"""<li class="#{classes.join(' ')}"#{style} data-option-array-index="#{option.array_index}">#{option.search_text}</li>"""
9196

9297
result_add_group: (group) ->
98+
return '' unless group.search_match || group.group_match
99+
return '' unless group.active_options > 0
100+
93101
"""<li class="group-result">#{group.search_text}</li>"""
94102

95103
results_update_field: ->
@@ -118,36 +126,48 @@ class AbstractChosen
118126
results = 0
119127

120128
searchText = this.get_search_text()
129+
escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
121130
regexAnchor = if @search_contains then "" else "^"
122-
regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
123-
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
131+
regex = new RegExp(regexAnchor + escapedSearchText, 'i')
132+
zregex = new RegExp(escapedSearchText, 'i')
124133

125134
for option in @results_data
126-
if not option.empty
127135

128-
option.group_match = false if option.group
136+
option.search_match = false
137+
results_group = null
138+
139+
if this.include_option_in_results(option)
129140

141+
if option.group
142+
option.group_match = false
143+
option.active_options = 0
144+
145+
if option.group_array_index? and @results_data[option.group_array_index]
146+
results_group = @results_data[option.group_array_index]
147+
results += 1 if results_group.active_options is 0 and results_group.search_match
148+
results_group.active_options += 1
149+
130150
unless option.group and not @group_search
131-
option.search_match = false
132151

133152
option.search_text = if option.group then option.label else option.html
134153
option.search_match = this.search_string_match(option.search_text, regex)
135-
results += 1 if option.search_match
154+
results += 1 if option.search_match and not option.group
136155

137156
if option.search_match
138157
if searchText.length
139158
startpos = option.search_text.search zregex
140159
text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length)
141160
option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos)
142161

143-
@results_data[option.group_array_index].group_match = true if option.group_array_index?
162+
results_group.group_match = true if results_group?
144163

145164
else if option.group_array_index? and @results_data[option.group_array_index].search_match
146165
option.search_match = true
147166

167+
this.result_clear_highlight()
168+
148169
if results < 1 and searchText.length
149170
this.update_results_content ""
150-
this.result_clear_highlight()
151171
this.no_results searchText
152172
else
153173
this.update_results_content this.results_option_build()
@@ -203,6 +223,13 @@ class AbstractChosen
203223
container_width: ->
204224
return if @options.width? then @options.width else "#{@form_field.offsetWidth}px"
205225

226+
include_option_in_results: (option) ->
227+
return false if @is_multiple and (not @display_selected_options and option.selected)
228+
return false if not @display_disabled_options and option.disabled
229+
return false if option.empty
230+
231+
return true
232+
206233
# class methods and variables ============================================================
207234

208235
@browser_is_supported: ->

contributing.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ preferred channel for [bug reports](#bugs), [features requests](#features)
2020
and [submitting pull requests](#pull-requests), but please respect the
2121
following restrictions:
2222

23-
* Please **do not** use the issue tracker for personal support requests (use
24-
[Stack Overflow](http://stackoverflow.com/search?q=chosen)).
23+
* Support issues or usage question that are not bugs should be posted on
24+
[Stack Overflow, using the `chosen.js`](http://stackoverflow.com/questions/tagged/chosen.js) tag
25+
(related tags: [`jquery-chosen`](http://stackoverflow.com/questions/tagged/jquery-chosen),
26+
[`prototype-chosen`](http://stackoverflow.com/questions/tagged/prototype-chosen)).
2527

2628
* Please **do not** derail or troll issues. Keep the discussion on topic and
2729
respect the opinions of others.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"author": "harvest",
33
"name": "chosen",
4-
"version": "0.13.0",
4+
"version": "0.14.0",
55
"description": "Chosen is a JavaScript plugin that makes long, unwieldy select boxes much more user-friendly. It is currently available in both jQuery and Prototype flavors.",
66
"repository": {
77
"type": "git",

public/options.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ <h3>Example:</h3>
9797
<td>Original select width.</td>
9898
<td>The width of the Chosen select box. By default, Chosen attempts to match the width of the select box you are replacing. If your select is hidden when Chosen is instantiated, you must specify a width or the select will show up with a width of 0.</td>
9999
</tr>
100+
<tr>
101+
<td>display_disabled_options</td>
102+
<td>true</td>
103+
<td>By default, Chosen includes disabled options in search results with a special styling. Setting this option to false will hide disabled results and exclude them from searches.</td>
104+
</tr>
105+
<tr>
106+
<td>display_selected_options</td>
107+
<td>true</td>
108+
<td>
109+
<p>By default, Chosen includes selected options in search results with a special styling. Setting this option to false will hide selected results and exclude them from searches.</p>
110+
<p><strong>Note:</strong> this is for multiple selects only. In single selects, the selected result will always be displayed.</p>
111+
</td>
112+
</tr>
100113
</table>
101114

102115
<h2><a name="attributes" class="anchor" href="#attributes">Attributes</a></h2>

0 commit comments

Comments
 (0)