chosen-rails-adding 1.0.2.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 00e7abb511cdea24c376e52968fddf09e4ed3399
4
+ data.tar.gz: d85dfad535dbfc9cb611e79b14859105a9b9b96d
5
+ SHA512:
6
+ metadata.gz: 718b969e82d5fba7550065e244af68b88f61349c967026e396ba5469988f733a545f84909e20d95ab0bb3f8e825f814fee5c8d93881f6232ca1e0ce6d6198645
7
+ data.tar.gz: f4630f7de81be963ddce127e2c7ad3af4773feeac8f496c162b3d28393e9fa176150477ac314a9c6e0f8bc4b8d30e1e0fe2ff79041582b3a3202dce7c511f53e
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in chosen-rails.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011-2013 by Tse-Ching Ho
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # Chosen for rails asset pipeline
2
+
3
+ [Chosen](https://github.com/harvesthq/chosen) is a library for making long, unwieldy select boxes more user friendly.
4
+
5
+ The `chosen-rails` gem integrates the `Chosen` with the Rails asset pipeline.
6
+
7
+ ## Usage
8
+
9
+ ### Install chosen-rails gem
10
+
11
+ Include `chosen-rails` in Gemefile
12
+
13
+ gem 'chosen-rails'
14
+
15
+ Then run `bundle install`
16
+
17
+ ### Include chosen javascript assets
18
+
19
+ Add to your `app/assets/javascripts/application.js` if use with jQuery
20
+
21
+ //= require chosen-jquery
22
+
23
+ Or with Prototype
24
+
25
+ //= require chosen-prototype
26
+
27
+ ### Include chosen stylesheet assets
28
+
29
+ Add to your `app/assets/stylesheets/application.css`
30
+
31
+ *= require chosen
32
+
33
+ ### Enable chosen javascript by specific css class
34
+
35
+ Add to one coffee script file, like `scaffold.js.coffee`
36
+
37
+ $ ->
38
+ # enable chosen js
39
+ $('.chosen-select').chosen
40
+ allow_single_deselect: true
41
+ no_results_text: 'No results matched'
42
+ width: '200px'
43
+
44
+ Notice: `width` option is required since `Chosen 0.9.15`.
45
+
46
+ And this file must be included in `application.js`
47
+
48
+ //= require chosen-jquery
49
+ //= require scaffold
50
+
51
+ Also add the class to your form field
52
+
53
+ <%= f.select :author,
54
+ User.all.map { |u| [u.name, u.id] },
55
+ { include_blank: true },
56
+ { class: 'chosen-select' }
57
+ %>
58
+
59
+ If you use simple form as form builder
60
+
61
+ <%= f.association :author,
62
+ collection: User.all,
63
+ include_blank: true,
64
+ input_html: { class: 'chosen-select' }
65
+ %>
66
+
67
+ ### Deployment
68
+
69
+ Since version 0.13.0, non-digested assets of `chosen-rails` will simply be copied from digested assets.
70
+
71
+ ## Gem maintenance
72
+
73
+ Maintain `chosen-rails` gem with `Rake` commands.
74
+
75
+ Update origin chosen source files.
76
+
77
+ rake update-chosen
78
+
79
+ Publish gem.
80
+
81
+ rake release
82
+
83
+ ## License
84
+
85
+ use MIT license.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require File.expand_path('../lib/chosen-rails-adding/source_file', __FILE__)
4
+
5
+ desc "Update with Harvest's Chosen Library"
6
+ task 'update-chosen', 'repository_url', 'branch' do |task, args|
7
+ remote = args['repository_url'] || 'https://github.com/koenpunt/chosen'
8
+ branch = args['branch'] || 'option_adding'
9
+ files = SourceFile.new
10
+ files.fetch remote, branch
11
+ files.eject_javascript_class_from_closure
12
+ files.cleanup
13
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/chosen-rails-adding/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Tse-Ching Ho']
6
+ gem.email = ['tsechingho@gmail.com']
7
+ gem.description = %q{Chosen is a javascript library of select box enhancer for jQuery and Protoype. This gem integrates Chosen with Rails asset pipeline for easy of use.}
8
+ gem.summary = %q{Integrate Chosen javascript library with Rails asset pipeline}
9
+ gem.homepage = 'https://github.com/spizm/chosen-rails-adding'
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = 'chosen-rails-adding'
15
+ gem.require_paths = ['lib']
16
+ gem.version = Chosen::Rails::VERSION
17
+
18
+ gem.add_dependency 'railties', '~> 4.0'
19
+ gem.add_dependency 'coffee-rails', '~> 4.0'
20
+ gem.add_dependency 'sass-rails', '~> 4.0'
21
+ gem.add_dependency 'compass-rails', '~> 1.1'
22
+
23
+ gem.add_development_dependency 'bundler', '~> 1.0'
24
+ gem.add_development_dependency 'rails', '~> 4.0'
25
+ gem.add_development_dependency 'thor', '~> 0.14'
26
+ end
@@ -0,0 +1,17 @@
1
+ require 'chosen-rails-adding/version'
2
+
3
+ module Chosen
4
+ module Rails
5
+ end
6
+ end
7
+
8
+ case ::Rails.version.to_s
9
+ when /^4/
10
+ require 'chosen-rails/engine'
11
+ when /^3\.[12]/
12
+ require 'chosen-rails/engine3'
13
+ when /^3\.[0]/
14
+ require 'chosen-rails/railtie'
15
+ end
16
+
17
+ require 'compass-rails'
@@ -0,0 +1,13 @@
1
+ module Chosen
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ config.assets.precompile += %w(
5
+ chosen-sprite*.png
6
+ )
7
+
8
+ rake_tasks do
9
+ load 'chosen-rails-adding/tasks.rake'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Chosen
2
+ module Rails
3
+ class Engine3 < ::Rails::Engine
4
+ initializer 'chosen.assets.precompile' do |app|
5
+ app.config.assets.precompile += %w(
6
+ chosen-sprite*.png
7
+ )
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Chosen
2
+ module Rails
3
+ class Railtie < ::Rails::Railtie
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,51 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ class SourceFile < Thor
5
+ include Thor::Actions
6
+
7
+ desc 'fetch source files', 'fetch source files from GitHub'
8
+ def fetch remote, branch
9
+ self.destination_root = 'vendor/assets'
10
+ get "#{remote}/raw/#{branch}/public/chosen-sprite.png", 'images/chosen-sprite.png'
11
+ get "#{remote}/raw/#{branch}/public/chosen-sprite@2x.png", 'images/chosen-sprite@2x.png'
12
+ get "#{remote}/raw/#{branch}/sass/chosen.scss", 'stylesheets/chosen.css.scss'
13
+ get "#{remote}/raw/#{branch}/coffee/lib/abstract-chosen.coffee", 'javascripts/lib/abstract-chosen.coffee'
14
+ get "#{remote}/raw/#{branch}/coffee/lib/select-parser.coffee", 'javascripts/lib/select-parser.coffee'
15
+ get "#{remote}/raw/#{branch}/coffee/chosen.jquery.coffee", 'javascripts/chosen.jquery.coffee'
16
+ get "#{remote}/raw/#{branch}/coffee/chosen.proto.coffee", 'javascripts/chosen.proto.coffee'
17
+ get "#{remote}/raw/#{branch}/package.json", 'package.json'
18
+ bump_version
19
+ end
20
+
21
+ desc 'eject class from closure', 'eject javascript library class from closure'
22
+ def eject_javascript_class_from_closure
23
+ self.destination_root = 'vendor/assets'
24
+ inside destination_root do
25
+ append_to_file 'javascripts/lib/abstract-chosen.coffee' do
26
+ "\nwindow.AbstractChosen = AbstractChosen\n"
27
+ end
28
+ append_to_file 'javascripts/lib/select-parser.coffee' do
29
+ "\n\nwindow.SelectParser = SelectParser\n"
30
+ end
31
+ end
32
+ end
33
+
34
+ desc 'clean up useless files', 'clean up useless files'
35
+ def cleanup
36
+ self.destination_root = 'vendor/assets'
37
+ remove_file 'package.json'
38
+ end
39
+
40
+ protected
41
+
42
+ def bump_version
43
+ inside destination_root do
44
+ package_json = JSON.load(File.open('package.json'))
45
+ version = package_json['version']
46
+ gsub_file '../../lib/chosen-rails/version.rb', /CHOSEN_VERSION\s=\s'(\d|\.)+'$/ do |match|
47
+ %Q{CHOSEN_VERSION = '#{version}'}
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ require 'fileutils'
2
+
3
+ desc 'Create nondigest versions of all chosen digest assets'
4
+ task 'assets:precompile' do
5
+ fingerprint = /\-[0-9a-f]{32}\./
6
+ Dir['public/assets/chosen-*'].each do |file|
7
+ next unless file =~ fingerprint
8
+ nondigest = file.sub fingerprint, '.'
9
+ FileUtils.cp file, nondigest, verbose: true
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Chosen
2
+ module Rails
3
+ VERSION = '1.0.2.1'
4
+ CHOSEN_VERSION = '1.0.0'
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ //= require lib/abstract-chosen
2
+ //= require lib/select-parser
3
+ //= require chosen.jquery
@@ -0,0 +1,3 @@
1
+ //= require lib/abstract-chosen
2
+ //= require lib/select-parser
3
+ //= require chosen.proto
@@ -0,0 +1,521 @@
1
+ $ = jQuery
2
+
3
+ $.fn.extend({
4
+ chosen: (options) ->
5
+ # Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
6
+ # Continue on if running IE document type but in compatibility mode
7
+ return this unless AbstractChosen.browser_is_supported()
8
+ this.each (input_field) ->
9
+ $this = $ this
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
+
18
+ })
19
+
20
+ class Chosen extends AbstractChosen
21
+
22
+ setup: ->
23
+ @form_field_jq = $ @form_field
24
+ @current_selectedIndex = @form_field.selectedIndex
25
+ @is_rtl = @form_field_jq.hasClass "chosen-rtl"
26
+
27
+ set_up_html: ->
28
+ container_classes = ["chosen-container"]
29
+ container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single")
30
+ container_classes.push @form_field.className if @inherit_select_classes && @form_field.className
31
+ container_classes.push "chosen-rtl" if @is_rtl
32
+
33
+ container_props =
34
+ 'class': container_classes.join ' '
35
+ 'style': "width: #{this.container_width()};"
36
+ 'title': @form_field.title
37
+
38
+ container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length
39
+
40
+ @container = ($ "<div />", container_props)
41
+
42
+ if @is_multiple
43
+ @container.html '<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + @default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'
44
+ else
45
+ @container.html '<a class="chosen-single chosen-default" tabindex="-1"><span>' + @default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'
46
+
47
+ @form_field_jq.hide().after @container
48
+ @dropdown = @container.find('div.chosen-drop').first()
49
+
50
+ @search_field = @container.find('input').first()
51
+ @search_results = @container.find('ul.chosen-results').first()
52
+ this.search_field_scale()
53
+
54
+ @search_no_results = @container.find('li.no-results').first()
55
+
56
+ if @is_multiple
57
+ @search_choices = @container.find('ul.chosen-choices').first()
58
+ @search_container = @container.find('li.search-field').first()
59
+ else
60
+ @search_container = @container.find('div.chosen-search').first()
61
+ @selected_item = @container.find('.chosen-single').first()
62
+
63
+ this.results_build()
64
+ this.set_tab_index()
65
+ this.set_label_behavior()
66
+ @form_field_jq.trigger("chosen:ready", {chosen: this})
67
+
68
+ register_observers: ->
69
+ @container.bind 'mousedown.chosen', (evt) => this.container_mousedown(evt); return
70
+ @container.bind 'mouseup.chosen', (evt) => this.container_mouseup(evt); return
71
+ @container.bind 'mouseenter.chosen', (evt) => this.mouse_enter(evt); return
72
+ @container.bind 'mouseleave.chosen', (evt) => this.mouse_leave(evt); return
73
+
74
+ @search_results.bind 'mouseup.chosen', (evt) => this.search_results_mouseup(evt); return
75
+ @search_results.bind 'mouseover.chosen', (evt) => this.search_results_mouseover(evt); return
76
+ @search_results.bind 'mouseout.chosen', (evt) => this.search_results_mouseout(evt); return
77
+ @search_results.bind 'mousewheel.chosen DOMMouseScroll.chosen', (evt) => this.search_results_mousewheel(evt); return
78
+
79
+ @search_results.bind 'touchstart.chosen', (evt) => this.search_results_touchstart(evt); return
80
+ @search_results.bind 'touchmove.chosen', (evt) => this.search_results_touchmove(evt); return
81
+ @search_results.bind 'touchend.chosen', (evt) => this.search_results_touchend(evt); return
82
+
83
+ @form_field_jq.bind "chosen:updated.chosen", (evt) => this.results_update_field(evt); return
84
+ @form_field_jq.bind "chosen:activate.chosen", (evt) => this.activate_field(evt); return
85
+ @form_field_jq.bind "chosen:open.chosen", (evt) => this.container_mousedown(evt); return
86
+ @form_field_jq.bind "chosen:close.chosen", (evt) => this.input_blur(evt); return
87
+
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
92
+
93
+ if @is_multiple
94
+ @search_choices.bind 'click.chosen', (evt) => this.choices_click(evt); return
95
+ else
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()
106
+
107
+ search_field_disabled: ->
108
+ @is_disabled = @form_field_jq[0].disabled
109
+ if(@is_disabled)
110
+ @container.addClass 'chosen-disabled'
111
+ @search_field[0].disabled = true
112
+ @selected_item.unbind "focus.chosen", @activate_action if !@is_multiple
113
+ this.close_field()
114
+ else
115
+ @container.removeClass 'chosen-disabled'
116
+ @search_field[0].disabled = false
117
+ @selected_item.bind "focus.chosen", @activate_action if !@is_multiple
118
+
119
+ container_mousedown: (evt) ->
120
+ if !@is_disabled
121
+ if evt and evt.type is "mousedown" and not @results_showing
122
+ evt.preventDefault()
123
+
124
+ if not (evt? and ($ evt.target).hasClass "search-choice-close")
125
+ if not @active_field
126
+ @search_field.val "" if @is_multiple
127
+ $(document).bind 'click.chosen', @click_test_action
128
+ this.results_show()
129
+ else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chosen-single").length)
130
+ evt.preventDefault()
131
+ this.results_toggle()
132
+
133
+ this.activate_field()
134
+
135
+ container_mouseup: (evt) ->
136
+ this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled
137
+
138
+ search_results_mousewheel: (evt) ->
139
+ delta = -evt.originalEvent.wheelDelta or evt.originalEvent.detail if evt.originalEvent
140
+ if delta?
141
+ evt.preventDefault()
142
+ delta = delta * 40 if evt.type is 'DOMMouseScroll'
143
+ @search_results.scrollTop(delta + @search_results.scrollTop())
144
+
145
+ blur_test: (evt) ->
146
+ this.close_field() if not @active_field and @container.hasClass "chosen-container-active"
147
+
148
+ close_field: ->
149
+ $(document).unbind "click.chosen", @click_test_action
150
+
151
+ @active_field = false
152
+ this.results_hide()
153
+
154
+ @container.removeClass "chosen-container-active"
155
+ this.clear_backstroke()
156
+
157
+ this.show_search_field_default()
158
+ this.search_field_scale()
159
+
160
+ activate_field: ->
161
+ @container.addClass "chosen-container-active"
162
+ @active_field = true
163
+
164
+ @search_field.val(@search_field.val())
165
+ @search_field.focus()
166
+
167
+
168
+ test_active_click: (evt) ->
169
+ if @container.is($(evt.target).closest('.chosen-container'))
170
+ @active_field = true
171
+ else
172
+ this.close_field()
173
+
174
+ results_build: ->
175
+ @parsing = true
176
+ @selected_option_count = null
177
+
178
+ @results_data = SelectParser.select_to_array @form_field
179
+
180
+ if @is_multiple
181
+ @search_choices.find("li.search-choice").remove()
182
+ else if not @is_multiple
183
+ this.single_set_selected_text()
184
+ if @disable_search or @form_field.options.length <= @disable_search_threshold and not @create_option
185
+ @search_field[0].readOnly = true
186
+ @container.addClass "chosen-container-single-nosearch"
187
+ else
188
+ @search_field[0].readOnly = false
189
+ @container.removeClass "chosen-container-single-nosearch"
190
+
191
+ this.update_results_content this.results_option_build({first:true})
192
+
193
+ this.search_field_disabled()
194
+ this.show_search_field_default()
195
+ this.search_field_scale()
196
+
197
+ @parsing = false
198
+
199
+ result_do_highlight: (el) ->
200
+ if el.length
201
+ this.result_clear_highlight()
202
+
203
+ @result_highlight = el
204
+ @result_highlight.addClass "highlighted"
205
+
206
+ maxHeight = parseInt @search_results.css("maxHeight"), 10
207
+ visible_top = @search_results.scrollTop()
208
+ visible_bottom = maxHeight + visible_top
209
+
210
+ high_top = @result_highlight.position().top + @search_results.scrollTop()
211
+ high_bottom = high_top + @result_highlight.outerHeight()
212
+
213
+ if high_bottom >= visible_bottom
214
+ @search_results.scrollTop if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
215
+ else if high_top < visible_top
216
+ @search_results.scrollTop high_top
217
+
218
+ result_clear_highlight: ->
219
+ @result_highlight.removeClass "highlighted" if @result_highlight
220
+ @result_highlight = null
221
+
222
+ results_show: ->
223
+ if @is_multiple and @max_selected_options <= this.choices_count()
224
+ @form_field_jq.trigger("chosen:maxselected", {chosen: this})
225
+ return false
226
+
227
+ @container.addClass "chosen-with-drop"
228
+ @form_field_jq.trigger("chosen:showing_dropdown", {chosen: this})
229
+
230
+ @results_showing = true
231
+
232
+ @search_field.focus()
233
+ @search_field.val @search_field.val()
234
+
235
+ this.winnow_results()
236
+
237
+ update_results_content: (content) ->
238
+ @search_results.html content
239
+
240
+ results_hide: ->
241
+ if @results_showing
242
+ this.result_clear_highlight()
243
+
244
+ @container.removeClass "chosen-with-drop"
245
+ @form_field_jq.trigger("chosen:hiding_dropdown", {chosen: this})
246
+
247
+ @results_showing = false
248
+
249
+
250
+ set_tab_index: (el) ->
251
+ if @form_field.tabIndex
252
+ ti = @form_field.tabIndex
253
+ @form_field.tabIndex = -1
254
+ @search_field[0].tabIndex = ti
255
+
256
+ set_label_behavior: ->
257
+ @form_field_label = @form_field_jq.parents("label") # first check for a parent label
258
+ if not @form_field_label.length and @form_field.id.length
259
+ @form_field_label = $("label[for='#{@form_field.id}']") #next check for a for=#{id}
260
+
261
+ if @form_field_label.length > 0
262
+ @form_field_label.bind 'click.chosen', (evt) => if @is_multiple then this.container_mousedown(evt) else this.activate_field()
263
+
264
+ show_search_field_default: ->
265
+ if @is_multiple and this.choices_count() < 1 and not @active_field
266
+ @search_field.val(@default_text)
267
+ @search_field.addClass "default"
268
+ else
269
+ @search_field.val("")
270
+ @search_field.removeClass "default"
271
+
272
+ search_results_mouseup: (evt) ->
273
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
274
+ if target.length
275
+ @result_highlight = target
276
+ this.result_select(evt)
277
+ @search_field.focus()
278
+
279
+ search_results_mouseover: (evt) ->
280
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
281
+ this.result_do_highlight( target ) if target
282
+
283
+ search_results_mouseout: (evt) ->
284
+ this.result_clear_highlight() if $(evt.target).hasClass "active-result" or $(evt.target).parents('.active-result').first()
285
+
286
+ choice_build: (item) ->
287
+ choice = $('<li />', { class: "search-choice" }).html("<span>#{item.html}</span>")
288
+
289
+ if item.disabled
290
+ choice.addClass 'search-choice-disabled'
291
+ else
292
+ close_link = $('<a />', { class: 'search-choice-close', 'data-option-array-index': item.array_index })
293
+ close_link.bind 'click.chosen', (evt) => this.choice_destroy_link_click(evt)
294
+ choice.append close_link
295
+
296
+ @search_container.before choice
297
+
298
+ choice_destroy_link_click: (evt) ->
299
+ evt.preventDefault()
300
+ evt.stopPropagation()
301
+ this.choice_destroy $(evt.target) unless @is_disabled
302
+
303
+ choice_destroy: (link) ->
304
+ if this.result_deselect( link[0].getAttribute("data-option-array-index") )
305
+ this.show_search_field_default()
306
+
307
+ this.results_hide() if @is_multiple and this.choices_count() > 0 and @search_field.val().length < 1
308
+
309
+ link.parents('li').first().remove()
310
+
311
+ this.search_field_scale()
312
+
313
+ results_reset: ->
314
+ this.reset_single_select_options()
315
+ @form_field.options[0].selected = true
316
+ this.single_set_selected_text()
317
+ this.show_search_field_default()
318
+ this.results_reset_cleanup()
319
+ @form_field_jq.trigger "change"
320
+ this.results_hide() if @active_field
321
+
322
+ results_reset_cleanup: ->
323
+ @current_selectedIndex = @form_field.selectedIndex
324
+ @selected_item.find("abbr").remove()
325
+
326
+ result_select: (evt) ->
327
+ if @result_highlight
328
+ high = @result_highlight
329
+
330
+ if high.hasClass "create-option"
331
+ this.select_create_option(@search_field.val())
332
+ return this.results_hide()
333
+
334
+ this.result_clear_highlight()
335
+
336
+ if @is_multiple and @max_selected_options <= this.choices_count()
337
+ @form_field_jq.trigger("chosen:maxselected", {chosen: this})
338
+ return false
339
+
340
+ if @is_multiple
341
+ high.removeClass("active-result")
342
+ else
343
+ this.reset_single_select_options()
344
+
345
+ item = @results_data[ high[0].getAttribute("data-option-array-index") ]
346
+ item.selected = true
347
+
348
+ @form_field.options[item.options_index].selected = true
349
+ @selected_option_count = null
350
+
351
+ if @is_multiple
352
+ this.choice_build item
353
+ else
354
+ this.single_set_selected_text(item.text)
355
+
356
+ this.results_hide() unless (evt.metaKey or evt.ctrlKey) and @is_multiple
357
+
358
+ @search_field.val ""
359
+
360
+ @form_field_jq.trigger "change", {'selected': @form_field.options[item.options_index].value} if @is_multiple || @form_field.selectedIndex != @current_selectedIndex
361
+ @current_selectedIndex = @form_field.selectedIndex
362
+ this.search_field_scale()
363
+
364
+ single_set_selected_text: (text=@default_text) ->
365
+ if text is @default_text
366
+ @selected_item.addClass("chosen-default")
367
+ else
368
+ this.single_deselect_control_build()
369
+ @selected_item.removeClass("chosen-default")
370
+
371
+ @selected_item.find("span").text(text)
372
+
373
+ result_deselect: (pos) ->
374
+ result_data = @results_data[pos]
375
+
376
+ if not @form_field.options[result_data.options_index].disabled
377
+ result_data.selected = false
378
+
379
+ @form_field.options[result_data.options_index].selected = false
380
+ @selected_option_count = null
381
+
382
+ this.result_clear_highlight()
383
+ this.winnow_results() if @results_showing
384
+
385
+ @form_field_jq.trigger "change", {deselected: @form_field.options[result_data.options_index].value}
386
+ this.search_field_scale()
387
+
388
+ return true
389
+ else
390
+ return false
391
+
392
+ single_deselect_control_build: ->
393
+ return unless @allow_single_deselect
394
+ @selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" unless @selected_item.find("abbr").length
395
+ @selected_item.addClass("chosen-single-with-deselect")
396
+
397
+ get_search_text: ->
398
+ if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()
399
+
400
+ winnow_results_set_highlight: ->
401
+ selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
402
+ do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
403
+
404
+ this.result_do_highlight do_high if do_high?
405
+
406
+ no_results: (terms) ->
407
+ no_results_html = $('<li class="no-results">' + @results_none_found + ' "<span></span>"</li>')
408
+ no_results_html.find("span").first().html(terms)
409
+ @search_results.append no_results_html
410
+
411
+ show_create_option: (terms) ->
412
+ create_option_html = $('<li class="create-option active-result"><a>' + @create_option_text + '</a>: "' + terms + '"</li>')
413
+ @search_results.append create_option_html
414
+
415
+ create_option_clear: ->
416
+ @search_results.find(".create-option").remove()
417
+
418
+ select_create_option: (terms) ->
419
+ if $.isFunction(@create_option)
420
+ @create_option.call this, terms
421
+ else
422
+ this.select_append_option( {value: terms, text: terms} )
423
+
424
+ select_append_option: ( options ) ->
425
+ option = $('<option />', options ).attr('selected', 'selected')
426
+ @form_field_jq.append option
427
+ @form_field_jq.trigger "chosen:updated"
428
+ @form_field_jq.trigger "change"
429
+ @search_field.trigger "focus"
430
+
431
+ no_results_clear: ->
432
+ @search_results.find(".no-results").remove()
433
+
434
+ keydown_arrow: ->
435
+ if @results_showing and @result_highlight
436
+ next_sib = @result_highlight.nextAll("li.active-result").first()
437
+ this.result_do_highlight next_sib if next_sib
438
+ else if @results_showing and @create_option
439
+ this.result_do_highlight(@search_results.find('.create-option'))
440
+ else
441
+ this.results_show()
442
+
443
+ keyup_arrow: ->
444
+ if not @results_showing and not @is_multiple
445
+ this.results_show()
446
+ else if @result_highlight
447
+ prev_sibs = @result_highlight.prevAll("li.active-result")
448
+
449
+ if prev_sibs.length
450
+ this.result_do_highlight prev_sibs.first()
451
+ else
452
+ this.results_hide() if this.choices_count() > 0
453
+ this.result_clear_highlight()
454
+
455
+ keydown_backstroke: ->
456
+ if @pending_backstroke
457
+ this.choice_destroy @pending_backstroke.find("a").first()
458
+ this.clear_backstroke()
459
+ else
460
+ next_available_destroy = @search_container.siblings("li.search-choice").last()
461
+ if next_available_destroy.length and not next_available_destroy.hasClass("search-choice-disabled")
462
+ @pending_backstroke = next_available_destroy
463
+ if @single_backstroke_delete
464
+ @keydown_backstroke()
465
+ else
466
+ @pending_backstroke.addClass "search-choice-focus"
467
+
468
+ clear_backstroke: ->
469
+ @pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke
470
+ @pending_backstroke = null
471
+
472
+ keydown_checker: (evt) ->
473
+ stroke = evt.which ? evt.keyCode
474
+ this.search_field_scale()
475
+
476
+ this.clear_backstroke() if stroke != 8 and this.pending_backstroke
477
+
478
+ switch stroke
479
+ when 8
480
+ @backstroke_length = this.search_field.val().length
481
+ break
482
+ when 9
483
+ this.result_select(evt) if this.results_showing and not @is_multiple
484
+ @mouse_on_container = false
485
+ break
486
+ when 13
487
+ evt.preventDefault()
488
+ break
489
+ when 38
490
+ evt.preventDefault()
491
+ this.keyup_arrow()
492
+ break
493
+ when 40
494
+ evt.preventDefault()
495
+ this.keydown_arrow()
496
+ break
497
+
498
+ search_field_scale: ->
499
+ if @is_multiple
500
+ h = 0
501
+ w = 0
502
+
503
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"
504
+ styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing']
505
+
506
+ for style in styles
507
+ style_block += style + ":" + @search_field.css(style) + ";"
508
+
509
+ div = $('<div />', { 'style' : style_block })
510
+ div.text @search_field.val()
511
+ $('body').append div
512
+
513
+ w = div.width() + 25
514
+ div.remove()
515
+
516
+ f_width = @container.outerWidth()
517
+
518
+ if( w > f_width - 10 )
519
+ w = f_width - 10
520
+
521
+ @search_field.css({'width': w + 'px'})