chosen-rails_ffcrm 0.9.5

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.
@@ -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