chosen-rails_ffcrm 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 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.
@@ -0,0 +1,47 @@
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/stylesheets/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
+ ## Gem maintainance
34
+
35
+ Maintain `chosen-rails` gem with `Rake` commands.
36
+
37
+ Update origin chosen source files.
38
+
39
+ rake update-chosen
40
+
41
+ Publish gem.
42
+
43
+ rake release
44
+
45
+ ## License
46
+
47
+ use MIT license.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require File.expand_path('../lib/chosen-rails/source_file', __FILE__)
4
+
5
+ desc "Update with Harvest's Chosen Library"
6
+ task "update-chosen" do
7
+ files = SourceFile.new
8
+ files.fetch
9
+ files.convert
10
+ files.cleanup
11
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/chosen-rails/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/tsechingho/chosen-rails"
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_ffcrm"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Chosen::Rails::VERSION
17
+
18
+ gem.add_dependency "railties", "~> 3.0"
19
+ gem.add_dependency "thor", "~> 0.14"
20
+ gem.add_development_dependency "bundler", "~> 1.0"
21
+ gem.add_development_dependency "rails", "~> 3.0"
22
+ gem.add_development_dependency "sass", "~> 3.1"
23
+ end
@@ -0,0 +1,11 @@
1
+ require "chosen-rails/version"
2
+
3
+ module Chosen
4
+ module Rails
5
+ if ::Rails.version < "3.1"
6
+ require "chosen-rails/railtie"
7
+ else
8
+ require "chosen-rails/engine"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Chosen
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ 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,42 @@
1
+ require "thor"
2
+
3
+ class SourceFile < Thor
4
+ include Thor::Actions
5
+
6
+ desc "fetch source files", "fetch source files from GitHub"
7
+ def fetch
8
+ self.destination_root = "vendor/assets"
9
+ remote = "https://github.com/fatfreecrm/chosen"
10
+ branch = "master"
11
+ get "#{remote}/raw/#{branch}/chosen/chosen-sprite.png", "images/chosen-sprite.png"
12
+ get "#{remote}/raw/#{branch}/chosen/chosen.css", "stylesheets/chosen.css"
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}/VERSION", "VERSION"
18
+ inside destination_root do
19
+ version = File.read("VERSION").sub("\n", "")
20
+ gsub_file "../../lib/chosen-rails/version.rb", /VERSION\s=\s"(\d|\.)+"$/ do |match|
21
+ %Q{VERSION = "#{version}"}
22
+ end
23
+ end
24
+ end
25
+
26
+ desc "convert css to sass file", "convert css to sass file by sass-convert"
27
+ def convert
28
+ self.destination_root = "vendor/assets"
29
+ inside destination_root do
30
+ run("sass-convert -F css -T sass stylesheets/chosen.css stylesheets/chosen.css.sass")
31
+ gsub_file 'stylesheets/chosen.css.sass', '(chosen-sprite.png)', "('chosen-sprite.png')"
32
+ gsub_file 'stylesheets/chosen.css.sass', ' url', ' image-url'
33
+ end
34
+ end
35
+
36
+ desc "clean up useless files", "clean up useless files"
37
+ def cleanup
38
+ self.destination_root = "vendor/assets"
39
+ remove_file "stylesheets/chosen.css"
40
+ remove_file "VERSION"
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ module Chosen
2
+ module Rails
3
+ VERSION = "0.9.5"
4
+ EDITOR_VERSION = "0.9.5"
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,574 @@
1
+ ###
2
+ Chosen source: generate output using 'cake build'
3
+ Copyright (c) 2011 by Harvest
4
+ ###
5
+ root = this
6
+ $ = jQuery
7
+
8
+ $.fn.extend({
9
+ chosen: (options) ->
10
+ # Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
11
+ return this if $.browser.msie and ($.browser.version is "6.0" or $.browser.version is "7.0")
12
+ $(this).each((input_field) ->
13
+ new Chosen(this, options) unless ($ this).hasClass "chzn-done"
14
+ )
15
+ })
16
+
17
+ class Chosen extends AbstractChosen
18
+
19
+ setup: ->
20
+ @form_field_jq = $ @form_field
21
+ @is_rtl = @form_field_jq.hasClass "chzn-rtl"
22
+
23
+ finish_setup: ->
24
+ @form_field_jq.addClass "chzn-done"
25
+
26
+ set_up_html: ->
27
+ @container_id = if @form_field.id.length then @form_field.id.replace(/(:|\.)/g, '_') else this.generate_field_id()
28
+ @container_id += "_chzn"
29
+
30
+ @f_width = @form_field_jq.outerWidth()
31
+
32
+ @default_text = if @form_field_jq.data 'placeholder' then @form_field_jq.data 'placeholder' else @default_text_default
33
+
34
+ container_div = ($ "<div />", {
35
+ id: @container_id
36
+ class: "chzn-container#{ if @is_rtl then ' chzn-rtl' else '' }"
37
+ style: 'width: ' + (@f_width) + 'px;' #use parens around @f_width so coffeescript doesn't think + ' px' is a function parameter
38
+ })
39
+
40
+ if @is_multiple
41
+ container_div.html '<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + @default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>'
42
+ else
43
+ container_div.html '<a href="javascript:void(0)" class="chzn-single"><span>' + @default_text + '</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>'
44
+
45
+ @form_field_jq.hide().after container_div
46
+ @container = ($ '#' + @container_id)
47
+ @container.addClass( "chzn-container-" + (if @is_multiple then "multi" else "single") )
48
+ @container.addClass "chzn-container-single-nosearch" if not @is_multiple and @form_field.options.length <= @disable_search_threshold
49
+ @dropdown = @container.find('div.chzn-drop').first()
50
+
51
+ dd_top = @container.height()
52
+ dd_width = (@f_width - get_side_border_padding(@dropdown))
53
+
54
+ @dropdown.css({"width": dd_width + "px", "top": dd_top + "px"})
55
+
56
+ @search_field = @container.find('input').first()
57
+ @search_results = @container.find('ul.chzn-results').first()
58
+ this.search_field_scale()
59
+
60
+ @search_no_results = @container.find('li.no-results').first()
61
+
62
+ if @is_multiple
63
+ @search_choices = @container.find('ul.chzn-choices').first()
64
+ @search_container = @container.find('li.search-field').first()
65
+ else
66
+ @search_container = @container.find('div.chzn-search').first()
67
+ @selected_item = @container.find('.chzn-single').first()
68
+ sf_width = dd_width - get_side_border_padding(@search_container) - get_side_border_padding(@search_field)
69
+ @search_field.css( {"width" : sf_width + "px"} )
70
+
71
+ this.results_build()
72
+ this.set_tab_index()
73
+ @form_field_jq.trigger("liszt:ready", {chosen: this})
74
+
75
+ register_observers: ->
76
+ @container.mousedown (evt) => this.container_mousedown(evt)
77
+ @container.mouseup (evt) => this.container_mouseup(evt)
78
+ @container.mouseenter (evt) => this.mouse_enter(evt)
79
+ @container.mouseleave (evt) => this.mouse_leave(evt)
80
+
81
+ @search_results.mouseup (evt) => this.search_results_mouseup(evt)
82
+ @search_results.mouseover (evt) => this.search_results_mouseover(evt)
83
+ @search_results.mouseout (evt) => this.search_results_mouseout(evt)
84
+
85
+ @form_field_jq.bind "liszt:updated", (evt) => this.results_update_field(evt)
86
+
87
+ @search_field.blur (evt) => this.input_blur(evt)
88
+ @search_field.keyup (evt) => this.keyup_checker(evt)
89
+ @search_field.keydown (evt) => this.keydown_checker(evt)
90
+
91
+ if @is_multiple
92
+ @search_choices.click (evt) => this.choices_click(evt)
93
+ @search_field.focus (evt) => this.input_focus(evt)
94
+
95
+ search_field_disabled: ->
96
+ @is_disabled = @form_field_jq.attr 'disabled'
97
+ if(@is_disabled)
98
+ @container.addClass 'chzn-disabled'
99
+ @search_field.attr 'disabled', true
100
+ @selected_item.unbind "focus", @activate_action if !@is_multiple
101
+ this.close_field()
102
+ else
103
+ @container.removeClass 'chzn-disabled'
104
+ @search_field.attr 'disabled', false
105
+ @selected_item.bind "focus", @activate_action if !@is_multiple
106
+
107
+ container_mousedown: (evt) ->
108
+ if !@is_disabled
109
+ target_closelink = if evt? then ($ evt.target).hasClass "search-choice-close" else false
110
+ if evt and evt.type is "mousedown" and not @results_showing
111
+ evt.stopPropagation()
112
+ if not @pending_destroy_click and not target_closelink
113
+ if not @active_field
114
+ @search_field.val "" if @is_multiple
115
+ $(document).click @click_test_action
116
+ this.results_show()
117
+ else if not @is_multiple and evt and ($(evt.target) is @selected_item || $(evt.target).parents("a.chzn-single").length)
118
+ evt.preventDefault()
119
+ this.results_toggle()
120
+
121
+ this.activate_field()
122
+ else
123
+ @pending_destroy_click = false
124
+
125
+ container_mouseup: (evt) ->
126
+ this.results_reset(evt) if evt.target.nodeName is "ABBR"
127
+
128
+ blur_test: (evt) ->
129
+ this.close_field() if not @active_field and @container.hasClass "chzn-container-active"
130
+
131
+ close_field: ->
132
+ $(document).unbind "click", @click_test_action
133
+
134
+ if not @is_multiple
135
+ @selected_item.attr "tabindex", @search_field.attr("tabindex")
136
+ @search_field.attr "tabindex", -1
137
+
138
+ @active_field = false
139
+ this.results_hide()
140
+
141
+ @container.removeClass "chzn-container-active"
142
+ this.winnow_results_clear()
143
+ this.clear_backstroke()
144
+
145
+ this.show_search_field_default()
146
+ this.search_field_scale()
147
+
148
+ activate_field: ->
149
+ if not @is_multiple and not @active_field
150
+ @search_field.attr "tabindex", (@selected_item.attr "tabindex")
151
+ @selected_item.attr "tabindex", -1
152
+
153
+ @container.addClass "chzn-container-active"
154
+ @active_field = true
155
+
156
+ @search_field.val(@search_field.val())
157
+ @search_field.focus()
158
+
159
+
160
+ test_active_click: (evt) ->
161
+ if $(evt.target).parents('#' + @container_id).length
162
+ @active_field = true
163
+ else
164
+ this.close_field()
165
+
166
+ results_build: ->
167
+ startTime = new Date()
168
+ @parsing = true
169
+ @results_data = root.SelectParser.select_to_array @form_field
170
+
171
+ if @is_multiple and @choices > 0
172
+ @search_choices.find("li.search-choice").remove()
173
+ @choices = 0
174
+ else if not @is_multiple
175
+ @selected_item.find("span").text @default_text
176
+
177
+ content = ''
178
+ for data in @results_data
179
+ if data.group
180
+ content += this.result_add_group data
181
+ else if !data.empty
182
+ content += this.result_add_option data
183
+ if data.selected and @is_multiple
184
+ this.choice_build data
185
+ else if data.selected and not @is_multiple
186
+ @selected_item.find("span").text data.text
187
+ this.single_deselect_control_build() if @allow_single_deselect
188
+
189
+ this.search_field_disabled()
190
+ this.show_search_field_default()
191
+ this.search_field_scale()
192
+
193
+ @search_results.html content
194
+ @parsing = false
195
+
196
+
197
+ result_add_group: (group) ->
198
+ if not group.disabled
199
+ group.dom_id = @container_id + "_g_" + group.array_index
200
+ '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>'
201
+ else
202
+ ""
203
+
204
+ result_do_highlight: (el) ->
205
+ if el.length
206
+ this.result_clear_highlight()
207
+
208
+ @result_highlight = el
209
+ @result_highlight.addClass "highlighted"
210
+
211
+ maxHeight = parseInt @search_results.css("maxHeight"), 10
212
+ visible_top = @search_results.scrollTop()
213
+ visible_bottom = maxHeight + visible_top
214
+
215
+ high_top = @result_highlight.position().top + @search_results.scrollTop()
216
+ high_bottom = high_top + @result_highlight.outerHeight()
217
+
218
+ if high_bottom >= visible_bottom
219
+ @search_results.scrollTop if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
220
+ else if high_top < visible_top
221
+ @search_results.scrollTop high_top
222
+
223
+ result_clear_highlight: ->
224
+ @result_highlight.removeClass "highlighted" if @result_highlight
225
+ @result_highlight = null
226
+
227
+ results_show: ->
228
+ if not @is_multiple
229
+ @selected_item.addClass "chzn-single-with-drop"
230
+ if @result_single_selected
231
+ this.result_do_highlight( @result_single_selected )
232
+
233
+ dd_top = if @is_multiple then @container.height() else (@container.height() - 1)
234
+ @dropdown.css {"top": dd_top + "px", "left":0}
235
+ @results_showing = true
236
+
237
+ @search_field.focus()
238
+ @search_field.val @search_field.val()
239
+
240
+ this.winnow_results()
241
+
242
+ results_hide: ->
243
+ @selected_item.removeClass "chzn-single-with-drop" unless @is_multiple
244
+ this.result_clear_highlight()
245
+ @dropdown.css {"left":"-9000px"}
246
+ @results_showing = false
247
+
248
+
249
+ set_tab_index: (el) ->
250
+ if @form_field_jq.attr "tabindex"
251
+ ti = @form_field_jq.attr "tabindex"
252
+ @form_field_jq.attr "tabindex", -1
253
+
254
+ if @is_multiple
255
+ @search_field.attr "tabindex", ti
256
+ else
257
+ @selected_item.attr "tabindex", ti
258
+ @search_field.attr "tabindex", -1
259
+
260
+ show_search_field_default: ->
261
+ if @is_multiple and @choices < 1 and not @active_field
262
+ @search_field.val(@default_text)
263
+ @search_field.addClass "default"
264
+ else
265
+ @search_field.val("")
266
+ @search_field.removeClass "default"
267
+
268
+ search_results_mouseup: (evt) ->
269
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
270
+ if target.length
271
+ @result_highlight = target
272
+ this.result_select(evt)
273
+
274
+ search_results_mouseover: (evt) ->
275
+ target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
276
+ this.result_do_highlight( target ) if target
277
+
278
+ search_results_mouseout: (evt) ->
279
+ this.result_clear_highlight() if $(evt.target).hasClass "active-result" or $(evt.target).parents('.active-result').first()
280
+
281
+
282
+ choices_click: (evt) ->
283
+ evt.preventDefault()
284
+ if( @active_field and not($(evt.target).hasClass "search-choice" or $(evt.target).parents('.search-choice').first) and not @results_showing )
285
+ this.results_show()
286
+
287
+ choice_build: (item) ->
288
+ choice_id = @container_id + "_c_" + item.array_index
289
+ @choices += 1
290
+ @search_container.before '<li class="search-choice" id="' + choice_id + '"><span>' + item.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>'
291
+ link = $('#' + choice_id).find("a").first()
292
+ link.click (evt) => this.choice_destroy_link_click(evt)
293
+
294
+ choice_destroy_link_click: (evt) ->
295
+ evt.preventDefault()
296
+ if not @is_disabled
297
+ @pending_destroy_click = true
298
+ this.choice_destroy $(evt.target)
299
+ else
300
+ evt.stopPropagation
301
+
302
+ choice_destroy: (link) ->
303
+ @choices -= 1
304
+ this.show_search_field_default()
305
+
306
+ this.results_hide() if @is_multiple and @choices > 0 and @search_field.val().length < 1
307
+
308
+ this.result_deselect (link.attr "rel")
309
+ link.parents('li').first().remove()
310
+
311
+ results_reset: (evt) ->
312
+ @form_field.options[0].selected = true
313
+ @selected_item.find("span").text @default_text
314
+ this.show_search_field_default()
315
+ $(evt.target).remove();
316
+ @form_field_jq.trigger "change"
317
+ this.results_hide() if @active_field
318
+
319
+ result_select: (evt) ->
320
+ if @result_highlight
321
+ high = @result_highlight
322
+ high_id = high.attr "id"
323
+
324
+ this.result_clear_highlight()
325
+
326
+ if @is_multiple
327
+ this.result_deactivate high
328
+ else
329
+ @search_results.find(".result-selected").removeClass "result-selected"
330
+ @result_single_selected = high
331
+
332
+ high.addClass "result-selected"
333
+
334
+ position = high_id.substr(high_id.lastIndexOf("_") + 1 )
335
+ item = @results_data[position]
336
+ item.selected = true
337
+
338
+ @form_field.options[item.options_index].selected = true
339
+
340
+ if @is_multiple
341
+ this.choice_build item
342
+ else
343
+ @selected_item.find("span").first().text item.text
344
+ this.single_deselect_control_build() if @allow_single_deselect
345
+
346
+ this.results_hide() unless evt.metaKey and @is_multiple
347
+
348
+ @search_field.val ""
349
+
350
+ @form_field_jq.trigger "change"
351
+ this.search_field_scale()
352
+ else if @options.allow_option_creation
353
+ new_option = @search_field.val()
354
+ return unless new_option
355
+ if @allow_creation(new_option)
356
+ $('<option>', {selected: true, value: new_option}).text(new_option).appendTo(@form_field_jq)
357
+ @results_update_field(evt)
358
+ @form_field_jq.trigger "change"
359
+ @search_field.val("")
360
+ @results_hide()
361
+
362
+ allow_creation: (new_option) ->
363
+ if @is_multiple
364
+ matches = @search_choices.find("li.search-choice span").filter ->
365
+ $(this).text().toLowerCase() == new_option.toLowerCase()
366
+ !matches.length
367
+ else
368
+ @selected_item.find('span').text().toLowerCase() != new_option.toLowerCase()
369
+
370
+ result_activate: (el) ->
371
+ el.addClass("active-result")
372
+
373
+ result_deactivate: (el) ->
374
+ el.removeClass("active-result")
375
+
376
+ result_deselect: (pos) ->
377
+ result_data = @results_data[pos]
378
+ result_data.selected = false
379
+
380
+ @form_field.options[result_data.options_index].selected = false
381
+ result = $("#" + @container_id + "_o_" + pos)
382
+ result.removeClass("result-selected").addClass("active-result").show()
383
+
384
+ this.result_clear_highlight()
385
+ this.winnow_results()
386
+
387
+ @form_field_jq.trigger "change"
388
+ this.search_field_scale()
389
+
390
+ single_deselect_control_build: ->
391
+ @selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" if @allow_single_deselect and @selected_item.find("abbr").length < 1
392
+
393
+ winnow_results: ->
394
+ startTime = new Date()
395
+ this.no_results_clear()
396
+
397
+ results = 0
398
+
399
+ searchText = if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()
400
+ textToSearch = searchText.replace(/[\-\[\]\{\}\(\)\*\+\?\.,\\\^\$\|\#\s]/g, "\\$&")
401
+ regex = new RegExp('^' + textToSearch, 'i')
402
+ zregex = new RegExp(textToSearch, 'i')
403
+ fregex = new RegExp("^" + textToSearch + "$", 'i')
404
+
405
+ for option in @results_data
406
+ if not option.disabled and not option.empty
407
+ if option.group
408
+ $('#' + option.dom_id).hide()
409
+ else if not (@is_multiple and option.selected)
410
+ found = false
411
+ result_id = option.dom_id
412
+
413
+ if @options.allow_option_creation && searchText && fregex.test(option.html)
414
+ found = true
415
+ results += 1
416
+ @result_do_highlight($('#' + option.dom_id))
417
+ else if regex.test option.html
418
+ found = true
419
+ results += 1
420
+ else if option.html.indexOf(" ") >= 0 or option.html.indexOf("[") == 0
421
+ #TODO: replace this substitution of /\[\]/ with a list of characters to skip.
422
+ parts = option.html.replace(/\[|\]/g, "").split(" ")
423
+ if parts.length
424
+ for part in parts
425
+ if regex.test part
426
+ found = true
427
+ results += 1
428
+
429
+ if found
430
+ if searchText.length
431
+ startpos = option.html.search zregex
432
+ text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length)
433
+ text = text.substr(0, startpos) + '<em>' + text.substr(startpos)
434
+ else
435
+ text = option.html
436
+
437
+ $("#" + result_id).html text if $("#" + result_id).html != text
438
+
439
+ this.result_activate $("#" + result_id)
440
+
441
+ $("#" + @results_data[option.group_array_index].dom_id).show() if option.group_array_index?
442
+ else
443
+ this.result_clear_highlight() if @result_highlight and result_id is @result_highlight.attr 'id'
444
+ this.result_deactivate $("#" + result_id)
445
+
446
+ if results < 1 and searchText.length
447
+ this.no_results searchText
448
+ @results_hide() if @options.allow_option_creation && @is_multiple
449
+ else if not @options.allow_option_creation
450
+ this.winnow_results_set_highlight()
451
+
452
+ winnow_results_clear: ->
453
+ @search_field.val ""
454
+ lis = @search_results.find("li")
455
+
456
+ for li in lis
457
+ li = $(li)
458
+ if li.hasClass "group-result"
459
+ li.show()
460
+ else if not @is_multiple or not li.hasClass "result-selected"
461
+ this.result_activate li
462
+
463
+ winnow_results_set_highlight: ->
464
+ if not @result_highlight
465
+
466
+ selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
467
+ do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
468
+
469
+ this.result_do_highlight do_high if do_high?
470
+
471
+ no_results: (terms) ->
472
+ return if !@is_multiple && @options.allow_option_creation
473
+ no_results_html = $('<li class="no-results">' + @results_none_found + ' "<span></span>"</li>')
474
+ no_results_html.find("span").first().html(terms)
475
+
476
+ @search_results.append no_results_html
477
+
478
+ no_results_clear: ->
479
+ @search_results.find(".no-results").remove()
480
+
481
+ keydown_arrow: ->
482
+ if not @result_highlight
483
+ first_active = @search_results.find("li.active-result").first()
484
+ this.result_do_highlight $(first_active) if first_active
485
+ else if @results_showing
486
+ next_sib = @result_highlight.nextAll("li.active-result").first()
487
+ this.result_do_highlight next_sib if next_sib
488
+ this.results_show() if not @results_showing
489
+
490
+ keyup_arrow: ->
491
+ if not @results_showing and not @is_multiple
492
+ this.results_show()
493
+ else if @result_highlight
494
+ prev_sibs = @result_highlight.prevAll("li.active-result")
495
+
496
+ if prev_sibs.length
497
+ this.result_do_highlight prev_sibs.first()
498
+ else
499
+ this.results_hide() if @choices > 0
500
+ this.result_clear_highlight()
501
+
502
+ keydown_backstroke: ->
503
+ if @pending_backstroke
504
+ this.choice_destroy @pending_backstroke.find("a").first()
505
+ this.clear_backstroke()
506
+ else
507
+ @pending_backstroke = @search_container.siblings("li.search-choice").last()
508
+ @pending_backstroke.addClass "search-choice-focus"
509
+
510
+ clear_backstroke: ->
511
+ @pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke
512
+ @pending_backstroke = null
513
+
514
+ keydown_checker: (evt) ->
515
+ stroke = evt.which ? evt.keyCode
516
+ this.search_field_scale()
517
+
518
+ this.clear_backstroke() if stroke != 8 and this.pending_backstroke
519
+
520
+ switch stroke
521
+ when 8
522
+ @backstroke_length = this.search_field.val().length
523
+ break
524
+ when 9
525
+ this.result_select(evt) if this.results_showing and not @is_multiple
526
+ @mouse_on_container = false
527
+ break
528
+ when 13
529
+ evt.preventDefault()
530
+ break
531
+ when 38
532
+ evt.preventDefault()
533
+ this.keyup_arrow()
534
+ break
535
+ when 40
536
+ this.keydown_arrow()
537
+ break
538
+
539
+ search_field_scale: ->
540
+ if @is_multiple
541
+ h = 0
542
+ w = 0
543
+
544
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"
545
+ styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing']
546
+
547
+ for style in styles
548
+ style_block += style + ":" + @search_field.css(style) + ";"
549
+
550
+ div = $('<div />', { 'style' : style_block })
551
+ div.text @search_field.val()
552
+ $('body').append div
553
+
554
+ w = div.width() + 25
555
+ div.remove()
556
+
557
+ if( w > @f_width-10 )
558
+ w = @f_width - 10
559
+
560
+ @search_field.css({'width': w + 'px'})
561
+
562
+ dd_top = @container.height()
563
+ @dropdown.css({"top": dd_top + "px"})
564
+
565
+ generate_random_id: ->
566
+ string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char()
567
+ while $("#" + string).length > 0
568
+ string += this.generate_random_char()
569
+ string
570
+
571
+ get_side_border_padding = (elmt) ->
572
+ side_border_padding = elmt.outerWidth() - elmt.width()
573
+
574
+ root.get_side_border_padding = get_side_border_padding