chosen-rails-adding 1.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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'})