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 ADDED
@@ -0,0 +1 @@
1
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,104 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chosen-awesome-rails (1.0.0)
5
+ coffee-rails (>= 3.2)
6
+ railties (>= 3.0)
7
+ sass-rails (>= 3.2)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ actionmailer (4.0.0)
13
+ actionpack (= 4.0.0)
14
+ mail (~> 2.5.3)
15
+ actionpack (4.0.0)
16
+ activesupport (= 4.0.0)
17
+ builder (~> 3.1.0)
18
+ erubis (~> 2.7.0)
19
+ rack (~> 1.5.2)
20
+ rack-test (~> 0.6.2)
21
+ activemodel (4.0.0)
22
+ activesupport (= 4.0.0)
23
+ builder (~> 3.1.0)
24
+ activerecord (4.0.0)
25
+ activemodel (= 4.0.0)
26
+ activerecord-deprecated_finders (~> 1.0.2)
27
+ activesupport (= 4.0.0)
28
+ arel (~> 4.0.0)
29
+ activerecord-deprecated_finders (1.0.3)
30
+ activesupport (4.0.0)
31
+ i18n (~> 0.6, >= 0.6.4)
32
+ minitest (~> 4.2)
33
+ multi_json (~> 1.3)
34
+ thread_safe (~> 0.1)
35
+ tzinfo (~> 0.3.37)
36
+ arel (4.0.0)
37
+ atomic (1.1.10)
38
+ builder (3.1.4)
39
+ coffee-rails (4.0.0)
40
+ coffee-script (>= 2.2.0)
41
+ railties (>= 4.0.0.beta, < 5.0)
42
+ coffee-script (2.2.0)
43
+ coffee-script-source
44
+ execjs
45
+ coffee-script-source (1.6.3)
46
+ erubis (2.7.0)
47
+ execjs (1.4.0)
48
+ multi_json (~> 1.0)
49
+ hike (1.2.3)
50
+ i18n (0.6.4)
51
+ mail (2.5.4)
52
+ mime-types (~> 1.16)
53
+ treetop (~> 1.4.8)
54
+ mime-types (1.23)
55
+ minitest (4.7.5)
56
+ multi_json (1.7.7)
57
+ polyglot (0.3.3)
58
+ rack (1.5.2)
59
+ rack-test (0.6.2)
60
+ rack (>= 1.0)
61
+ rails (4.0.0)
62
+ actionmailer (= 4.0.0)
63
+ actionpack (= 4.0.0)
64
+ activerecord (= 4.0.0)
65
+ activesupport (= 4.0.0)
66
+ bundler (>= 1.3.0, < 2.0)
67
+ railties (= 4.0.0)
68
+ sprockets-rails (~> 2.0.0)
69
+ railties (4.0.0)
70
+ actionpack (= 4.0.0)
71
+ activesupport (= 4.0.0)
72
+ rake (>= 0.8.7)
73
+ thor (>= 0.18.1, < 2.0)
74
+ rake (10.1.0)
75
+ sass (3.2.10)
76
+ sass-rails (4.0.0)
77
+ railties (>= 4.0.0.beta, < 5.0)
78
+ sass (>= 3.1.10)
79
+ sprockets-rails (~> 2.0.0)
80
+ sprockets (2.10.0)
81
+ hike (~> 1.2)
82
+ multi_json (~> 1.0)
83
+ rack (~> 1.0)
84
+ tilt (~> 1.1, != 1.3.0)
85
+ sprockets-rails (2.0.0)
86
+ actionpack (>= 3.0)
87
+ activesupport (>= 3.0)
88
+ sprockets (~> 2.8)
89
+ thor (0.18.1)
90
+ thread_safe (0.1.2)
91
+ atomic
92
+ tilt (1.4.1)
93
+ treetop (1.4.14)
94
+ polyglot
95
+ polyglot (>= 0.3.1)
96
+ tzinfo (0.3.37)
97
+
98
+ PLATFORMS
99
+ ruby
100
+
101
+ DEPENDENCIES
102
+ bundler (>= 1.0)
103
+ chosen-awesome-rails!
104
+ rails (>= 3.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 heaven
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Chosen awesome (with ajax support and dynamic options injection)
2
+
3
+ A written from the scratch library that wraps around default html select controls
4
+ and makes them more user friendly (Ruby on Rails package).
5
+
6
+ ## Usage
7
+
8
+ ### Install chosen-awesome-rails gem
9
+
10
+ Include `chosen-awesome-rails` in Gemefile
11
+
12
+ gem 'chosen-awesome-rails'
13
+
14
+ Then run `bundle install`
15
+
16
+ ### Include javascript assets
17
+
18
+ Add to your `app/assets/javascripts/application.js`
19
+
20
+ //= require chosen
21
+
22
+ ### Include chosen stylesheet assets
23
+
24
+ Add to your `app/assets/stylesheets/application.css`
25
+
26
+ *= require chosen
27
+
28
+ You might also use twitter bootstrap integration by adding
29
+
30
+ *= require chosen/bootstrap
31
+
32
+ ### Enable chosen
33
+ ```javascript
34
+ $("select").chosen()
35
+ ```
36
+
37
+ Default options are:
38
+
39
+ ```javascript
40
+ {
41
+ allow_insertion: false, // allows to add missing options dynamically, e.g. when you
42
+ // need to show a list of tags allowing users to add missing ones
43
+ inherit_classes: true, // whether chosen should inherit html class names from the
44
+ // original select element
45
+ option_parser: null, // a function that should return an object that
46
+ // will be passed right to jQuery's append method to build
47
+ // html option elemets: $("<option />", parsed_object)
48
+ option_formatter: null // a function that accepts an option object (jquery selector)
49
+ // and returns an array of 2 values where one is used
50
+ // for the dropdown item and another for the choice element
51
+ }
52
+ ```
53
+
54
+ Dynamic insertion example:
55
+
56
+ ![Dynamic insertion example]
57
+ (http://oi62.tinypic.com/14kb808.jpg)
58
+
59
+ The option formatter allows to build selects like this one:
60
+
61
+ ![Custom dropdown options]
62
+ (http://oi60.tinypic.com/28818i8.jpg)
63
+
64
+ You can also override text messages with:
65
+
66
+ ```javascript
67
+ {
68
+ locale: {
69
+ no_results: "No results found",
70
+ start_typing: "Please start typing",
71
+ add_new: "add new"
72
+ }
73
+ }
74
+ ```
75
+
76
+ And pass the next ajax options:
77
+
78
+ ```javascript
79
+ {
80
+ ajax: {
81
+ url: "where to fetch options",
82
+ type: "get", // optional
83
+ dataType: "json", // optional
84
+ data: {}, // optional
85
+ async: true, // optional
86
+ xhrFields: null // optional
87
+ }
88
+ }
89
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: chosen-awesome-rails 0.0.1 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "chosen-awesome-rails"
6
+ s.version = "1.0.0"
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib"]
10
+ s.authors = ["heaven"]
11
+ s.date = "2013-08-04"
12
+ s.description = "Chosen is a javascript library of select box enhancer for jQuery, integrates with Rails asset pipeline for ease of use."
13
+ s.email = ["alex@codeart.pw"]
14
+ s.files = [".gitignore", "Gemfile", "Gemfile.lock", "LICENSE.txt", "README.md", "Rakefile", "chosen-awesome-rails.gemspec", "lib/chosen-awesome-rails.rb", "lib/chosen-awesome-rails/engine.rb", "lib/chosen-awesome-rails/engine3.rb", "lib/chosen-awesome-rails/version.rb", "vendor/assets/images/chosen-arrow.gif", "vendor/assets/javascripts/chosen.js.coffee", "vendor/assets/javascripts/chosen/chosen.js.coffee", "vendor/assets/javascripts/chosen/multiple.js.coffee", "vendor/assets/javascripts/chosen/parser.js.coffee", "vendor/assets/javascripts/chosen/single.js.coffee", "vendor/assets/stylesheets/chosen.css.scss", "vendor/assets/stylesheets/chosen/bootstrap.css.scss", "vendor/assets/stylesheets/chosen/default.css.scss"]
15
+ s.homepage = "https://github.com/heaven/chosen-awesome-rails"
16
+ s.rubygems_version = "2.2.1"
17
+ s.summary = "Integrate Chosen javascript library with Rails asset pipeline"
18
+
19
+ if s.respond_to? :specification_version then
20
+ s.specification_version = 3
21
+
22
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
+ s.add_runtime_dependency(%q<railties>, [">= 3.0"])
24
+ s.add_runtime_dependency(%q<coffee-rails>, [">= 3.2"])
25
+ s.add_runtime_dependency(%q<sass-rails>, [">= 3.2"])
26
+ s.add_development_dependency(%q<bundler>, [">= 1.0"])
27
+ s.add_development_dependency(%q<rails>, [">= 3.0"])
28
+ else
29
+ s.add_dependency(%q<railties>, [">= 3.0"])
30
+ s.add_dependency(%q<coffee-rails>, [">= 3.2"])
31
+ s.add_dependency(%q<sass-rails>, [">= 3.2"])
32
+ s.add_dependency(%q<bundler>, [">= 1.0"])
33
+ s.add_dependency(%q<rails>, [">= 3.0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<railties>, [">= 3.0"])
37
+ s.add_dependency(%q<coffee-rails>, [">= 3.2"])
38
+ s.add_dependency(%q<sass-rails>, [">= 3.2"])
39
+ s.add_dependency(%q<bundler>, [">= 1.0"])
40
+ s.add_dependency(%q<rails>, [">= 3.0"])
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module Chosen
2
+ module Rails
3
+ end
4
+ end
5
+
6
+ require 'chosen-awesome-rails/version'
7
+
8
+ case ::Rails.version.to_s
9
+ when /^4/
10
+ require 'chosen-awesome-rails/engine'
11
+ when /^3\.[12]/
12
+ require 'chosen-awesome-rails/engine3'
13
+ end
@@ -0,0 +1,7 @@
1
+ module Chosen
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ config.assets.precompile += %w[chosen-*.gif chosen-*.png]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Chosen
2
+ module Rails
3
+ class Engine3 < ::Rails::Engine
4
+ initializer 'chosen.assets.precompile' do |app|
5
+ app.config.assets.precompile += %w[chosen-*.gif chosen-*.png]
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Chosen
2
+ module Rails
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,39 @@
1
+ #= require chosen/chosen
2
+ #= require chosen/multiple
3
+ #= require chosen/single
4
+ #= require chosen/parser
5
+
6
+ $ = jQuery
7
+
8
+ $.fn.extend
9
+ chosen: (options) ->
10
+ return @ unless Chosen.is_supported()
11
+
12
+ @each ->
13
+ $this = $(@)
14
+
15
+ unless $this.data("chosen")
16
+ $this.data('chosen',
17
+ if @multiple
18
+ new Chosen.Multiple($this, options)
19
+ else
20
+ new Chosen.Single($this, options)
21
+ ).trigger("chosen:ready")
22
+
23
+ $(window).bind("resize", (evt) ->
24
+ for chosen in Chosen.pool
25
+ chosen.update_dropdown_position()
26
+
27
+ return
28
+ ).bind "scroll", (evt) ->
29
+ for chosen in Chosen.pool
30
+ chosen.close() if chosen.opened
31
+
32
+ return
33
+
34
+ $(document).ready ->
35
+ $("body").on "click", "input[type=reset]", (evt) ->
36
+ $(evt.target.form).find("select.chosen").each ->
37
+ chosen = $(@).data("chosen")
38
+ chosen and chosen.reset()
39
+
@@ -0,0 +1,470 @@
1
+ $ = jQuery
2
+
3
+ class Chosen
4
+ constructor: (@$target, options = {}) ->
5
+ $.extend(@, $.extend($.extend($.extend({}, Chosen.defaults), @constructor.defaults), options))
6
+
7
+ @$body = $("body")
8
+ @target = @$target[0]
9
+ @parser = new Chosen.Parser(@)
10
+ @default_values = $.map @parser.selected_options, (option) -> option
11
+
12
+ @allow_deselect = @is_multiple or (@parser.includes_blank() and @allow_deselect != false)
13
+ @activated = false
14
+ @opened = false
15
+
16
+ @search_value = ""
17
+ @cursor_option = null
18
+
19
+ @build()
20
+ @load()
21
+ @complete()
22
+
23
+ complete: ->
24
+ Chosen.pool.push(@)
25
+
26
+ if @target.disabled
27
+ @disabled = false
28
+ @disable()
29
+ else
30
+ @disabled = true
31
+ @enable()
32
+
33
+ @$target.addClass("chosen").after(@$container)
34
+
35
+ destroy: ->
36
+ @unbind_events()
37
+
38
+ delete @$body
39
+
40
+ @$container.remove()
41
+ @$dropdown.remove()
42
+ @$target.removeData("chosen").removeClass("chosen").show()
43
+
44
+ delete @$container
45
+ delete @$dropdown
46
+ delete @$target
47
+ delete @target
48
+
49
+ @parser.destroy()
50
+
51
+ delete @parser
52
+
53
+ index = Chosen.pool.indexOf(@)
54
+ Chosen.pool.splice(index, 1) if index >= 0
55
+
56
+ reset: ->
57
+ @deselect_all()
58
+
59
+ $.each @default_values, (index, option) =>
60
+ @parser.restore(option)
61
+
62
+ @load()
63
+
64
+ build: ->
65
+ select_classes = ["chosen-container"]
66
+
67
+ select_classes.push if @is_multiple then "multiple" else "single"
68
+ select_classes.push "rtl" if @is_rtl
69
+ select_classes.push @target.className if @inherit_classes and @target.className
70
+
71
+ width = if @width? then @width else "#{@target.offsetWidth}px"
72
+
73
+ container_props =
74
+ class: select_classes.join ' '
75
+ style: "width: #{width}; min-width: #{width}; max-width: #{width}"
76
+
77
+ container_props.title = @target.title if @target.title.length
78
+ container_props.id = @target.id.replace(/[^\w]/g, '-') + "-chosen" if @target.id
79
+ placeholder = @$target.attr("placeholder") || @placeholder
80
+
81
+ @$container = $("<div />", container_props)
82
+ @$container.html "<ul class=\"chosen-choices\"><li class=\"chosen-search-field\"><input type=\"text\" placeholder=\"#{placeholder}\" autocomplete=\"off\" /></li></ul>"
83
+ @$container.$choices = @$container.find("ul.chosen-choices")
84
+ @$container.$search_container = @$container.$choices.find("li.chosen-search-field")
85
+ @$container.$search = @$container.$choices.find("input[type=text]").attr(tabindex: @target.tabindex || "0")
86
+
87
+ dropdown_classes = ["chosen-dropdown"]
88
+
89
+ dropdown_classes.push if @is_multiple then "multiple" else "single"
90
+ dropdown_classes.push "rtl" if @is_rtl
91
+
92
+ dropdown_props =
93
+ class: dropdown_classes.join ' '
94
+ unselectable: "on"
95
+ html: "<ul></ul>"
96
+
97
+ @$dropdown = $("<div />", dropdown_props)
98
+ @$dropdown.$list = @$dropdown.find("ul").first()
99
+ @$dropdown.$list.$no_results = $("<li />", class: "chosen-noresults")
100
+ @$dropdown.$list.suggestion = null
101
+
102
+ bind_events: ->
103
+ if @target.id.length
104
+ $("label[for=#{@target.id}]").bind "click", (evt) =>
105
+ @$container.$search.trigger("focus")
106
+ @open()
107
+ evt.preventDefault()
108
+
109
+ @$container.bind "mousedown", (evt) =>
110
+ @$container.$search.trigger("focus")
111
+ @open()
112
+ evt.preventDefault()
113
+
114
+ @$container.$search.bind "mousedown", (evt) =>
115
+ @$container.$search.trigger("focus")
116
+ @open()
117
+ evt.stopImmediatePropagation()
118
+
119
+ @$container.$search.bind "keydown", (evt) => @keydown(evt)
120
+ @$container.$search.bind "keyup", (evt) => @keyup(evt)
121
+ @$container.$search.bind "focus", (evt) => @focus(evt)
122
+ @$container.$search.bind "blur", (evt) => @blur(evt)
123
+
124
+ return true
125
+
126
+ unbind_events: ->
127
+ if @target.id.length
128
+ $("label[for=#{@target.id}]").unbind "click"
129
+
130
+ @$dropdown.unbind()
131
+ @$container.$search.unbind()
132
+ @$container.unbind()
133
+
134
+ return true
135
+
136
+ activate: ->
137
+ @$container.$search.trigger("focus")
138
+ return @
139
+
140
+ deactivate: ->
141
+ @$container.$search.trigger("blur")
142
+ return @
143
+
144
+ enable: ->
145
+ if @disabled
146
+ @$target.removeAttr("disabled")
147
+ @$container.$search.removeAttr("disabled")
148
+ @$container.removeClass("disabled")
149
+ @$container.find("a").each ->
150
+ $(@).attr(tabindex: @tabindex) if @tabindex
151
+
152
+ @bind_events()
153
+ @disabled = false
154
+
155
+ return @
156
+
157
+ disable: ->
158
+ unless @disabled
159
+ @close()
160
+ @blur()
161
+ @unbind_events()
162
+
163
+ @$container.find("a").each(->
164
+ $link = $(@)
165
+
166
+ @tabindex = $link.attr("tabindex")
167
+ $link.attr(tabindex: "-1")
168
+ )
169
+
170
+ @$container.addClass("disabled")
171
+ @$container.$search.attr(disabled: "disabled")
172
+ @$target.attr(disabled: "disabled")
173
+ @disabled = true
174
+
175
+ return @
176
+
177
+ focus: (evt) ->
178
+ return @ if @activated
179
+
180
+ @activated = true
181
+ @$container.addClass("focus")
182
+
183
+ return @
184
+
185
+ blur: (evt) ->
186
+ return @ unless @activated
187
+
188
+ @set_default_value()
189
+ @close()
190
+ @activated = false
191
+ @$container.removeClass("focus")
192
+
193
+ return @
194
+
195
+ open: ->
196
+ return @ if @opened
197
+
198
+ @opened = true
199
+
200
+ @redraw_dropdown()
201
+
202
+ @$container.$search.trigger("focus") unless @activated
203
+ @$body.append(@$dropdown)
204
+
205
+ @move_selection_to(@parser.index_of(@cursor_option))
206
+
207
+ @$dropdown.bind "mouseover", "li.chosen-option", (evt) => @dropdown_mouseover(evt)
208
+ @$dropdown.bind "mousedown", "li.chosen-option", (evt) => @dropdown_mousedown(evt)
209
+
210
+ @$container.addClass("opened")
211
+ @$dropdown.addClass("opened")
212
+
213
+ return @
214
+
215
+ close: ->
216
+ return @ unless @opened
217
+
218
+ @$container.removeClass("opened")
219
+ @$dropdown.removeClass("opened")
220
+ @$dropdown.unbind "mouseover mousedown"
221
+ @$dropdown.remove()
222
+ @opened = false
223
+
224
+ return @
225
+
226
+ loading: ->
227
+ @loaded()
228
+ @$container.addClass("loading")
229
+ @$dropdown.addClass("loading")
230
+ return @
231
+
232
+ loaded: ->
233
+ @$container.removeClass("loading error")
234
+ @$dropdown.removeClass("loading error")
235
+ return @
236
+
237
+ error: ->
238
+ @loaded()
239
+ @$container.addClass("error")
240
+ @$dropdown.addClass("error")
241
+ return @
242
+
243
+ dropdown_mouseover: (evt) ->
244
+ option = @parser.find_by_element(evt.target)
245
+
246
+ @move_selection_to(@parser.index_of(option)) if option
247
+
248
+ evt.preventDefault()
249
+ evt.stopImmediatePropagation()
250
+ return
251
+
252
+ dropdown_mousedown: (evt) ->
253
+ option = @parser.find_by_element(evt.target)
254
+
255
+ @select(option) if option
256
+
257
+ evt.preventDefault()
258
+ evt.stopImmediatePropagation()
259
+ return
260
+
261
+ keydown: (evt) ->
262
+ code = evt.which ? evt.keyCode
263
+
264
+ switch code
265
+ when 13
266
+ if @opened
267
+ @select(@cursor_option)
268
+ @move_selection(1) if @is_multiple
269
+ else
270
+ @open()
271
+ evt.preventDefault()
272
+ when 27
273
+ evt.preventDefault()
274
+ evt.stopPropagation()
275
+ when 38, 40
276
+ @open()
277
+ @move_selection(code - 39)
278
+ evt.preventDefault()
279
+ else
280
+ true
281
+
282
+ return
283
+
284
+ keyup: (evt) ->
285
+ code = evt.which ? evt.keyCode
286
+
287
+ return if [9, 13, 16, 35, 36, 37, 38, 39, 40].indexOf(code) >= 0
288
+
289
+ if code is 27 and @opened
290
+ @close()
291
+ evt.stopPropagation()
292
+ else if @has_filter_changed()
293
+ @open()
294
+
295
+ if @ajax then @pull_updates() else @redraw_dropdown()
296
+
297
+ return
298
+
299
+ redraw_dropdown: (data) ->
300
+ @parser.update(data) unless data is undefined
301
+
302
+ changed = @apply_filter()
303
+
304
+ @update_dropdown_position()
305
+ @update_dropdown_content()
306
+ @move_selection_to(0) if changed
307
+
308
+ return
309
+
310
+ update_dropdown_position: ->
311
+ return unless @opened
312
+
313
+ list = @$container.find("ul")
314
+ offsets = list.offset()
315
+ height = list.innerHeight()
316
+ width = list.innerWidth()
317
+
318
+ @$dropdown.css
319
+ left: "#{offsets.left}px",
320
+ top: "#{offsets.top + height}px"
321
+ width: "#{width}px"
322
+
323
+ return
324
+
325
+ update_dropdown_content: ->
326
+ @insert_suggestion()
327
+
328
+ if @parser.selectable_options.length
329
+ @$dropdown.$list.html(@parser.to_html())
330
+ else
331
+ @show_no_results()
332
+
333
+ return
334
+
335
+ insert_suggestion: ->
336
+ return unless @allow_insertion
337
+
338
+ if @$dropdown.$list.suggestion
339
+ @parser.remove(@$dropdown.$list.suggestion)
340
+
341
+ if @$container.$search[0].value and not @parser.exact_matches().length
342
+ @$dropdown.$list.suggestion = suggestion = @parser.insert(
343
+ value: @$container.$search[0].value
344
+ label: @$container.$search[0].value
345
+ )
346
+
347
+ value = "#{suggestion.value} (#{@locale.add_new})"
348
+
349
+ suggestion.$listed.contents().last()[0].nodeValue = value
350
+ suggestion.$choice.contents().last()[0].nodeValue = value
351
+ else if @$dropdown.$list.suggestion
352
+ @$dropdown.$list.suggestion = null
353
+
354
+ show_no_results: ->
355
+ text = if @ajax then @locale.start_typing else @locale.no_results
356
+
357
+ @$dropdown.$list.$no_results.text(text)
358
+ @$dropdown.$list.html(@$dropdown.$list.$no_results)
359
+
360
+ apply_filter: ->
361
+ return false unless @has_filter_changed()
362
+
363
+ @search_value = @$container.$search[0].value
364
+ @parser.apply_filter(@$container.$search[0].value)
365
+
366
+ true
367
+
368
+ has_filter_changed: ->
369
+ @search_value isnt @$container.$search[0].value
370
+
371
+ move_selection: (dir) ->
372
+ cursor = @parser.index_of(@cursor_option) + dir
373
+ cursor = @parser.available_options.length - 1 if cursor < 0
374
+ cursor = 0 if cursor > @parser.available_options.length - 1
375
+
376
+ @move_selection_to(cursor)
377
+
378
+ if @cursor_option and @cursor_option.selected and @parser.selectable_options.length
379
+ # TODO: optimize this
380
+ return @move_selection(dir)
381
+
382
+ return @
383
+
384
+ move_selection_to: (cursor) ->
385
+ if @cursor_option
386
+ @cursor_option.$listed.removeClass("active")
387
+
388
+ @cursor_option = @parser.available_options[cursor]
389
+
390
+ return unless @cursor_option
391
+
392
+ $element = @cursor_option.$listed.addClass("active")
393
+ top = $element.position().top + $element.height()
394
+ list_height = @$dropdown.height()
395
+ list_scroll = @$dropdown.scrollTop()
396
+
397
+ if top >= list_height + list_scroll or list_scroll >= top
398
+ @$dropdown.scrollTop($element.position().top)
399
+
400
+ return @
401
+
402
+ get_caret_position: ->
403
+ field = @$container.$search[0]
404
+
405
+ if document.selection
406
+ sel = document.selection.createRange()
407
+ length = sel.text.length
408
+
409
+ sel.moveStart('character', -field.value.length)
410
+
411
+ sel.text.length - length
412
+ else if field.selectionStart or field.selectionStart is '0'
413
+ field.selectionStart
414
+ else
415
+ 0
416
+
417
+ pull_updates: ->
418
+ return @ if not @ajax or not @$container.$search[0].value
419
+
420
+ if @ajax.pending_update
421
+ clearTimeout(@ajax.pending_update)
422
+
423
+ @ajax.pending_update = setTimeout =>
424
+ if @ajax.pending_request and @ajax.pending_request.readyState isnt 4
425
+ @ajax.pending_request.abort()
426
+
427
+ data =
428
+ query: @$container.$search[0].value
429
+
430
+ @ajax.pending_request = $.ajax
431
+ url: @ajax.url
432
+ type: @ajax.type or "get"
433
+ dataType: @ajax.dataType or "json"
434
+ data: $.extend(@ajax.data || {}, data)
435
+ async: @ajax.async or true
436
+ xhrFields: @ajax.xhrFields
437
+
438
+ beforeSend: (xhr) =>
439
+ @loading()
440
+ @ajax.beforeSend(xhr) if typeof @ajax.beforeSend is "function"
441
+ success: (data) =>
442
+ @loaded()
443
+ @redraw_dropdown(data)
444
+ error: =>
445
+ @error()
446
+
447
+ , 300
448
+
449
+ return @
450
+
451
+ @is_crappy_browser: (version) ->
452
+ window.navigator.appName == "Microsoft Internet Explorer" and document.documentMode <= version
453
+
454
+ @is_supported: ->
455
+ not Chosen.is_crappy_browser(6)
456
+
457
+ @defaults:
458
+ allow_insertion: false
459
+ inherit_classes: true
460
+ is_rtl: false
461
+ option_parser: null
462
+ option_formatter: null
463
+ locale:
464
+ no_results: "No results found"
465
+ start_typing: "Please start typing"
466
+ add_new: "add new"
467
+
468
+ @pool: []
469
+
470
+ @Chosen = Chosen