chosen-rails 0.9.5

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