ab_admin 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Gemfile +5 -2
  2. data/README.md +2 -4
  3. data/TODO +3 -0
  4. data/ab_admin.gemspec +1 -1
  5. data/app/assets/javascripts/ab_admin/application.js +4 -1
  6. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +23 -0
  7. data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +4 -1
  8. data/app/assets/javascripts/ab_admin/core/columns_hider.js.coffee +13 -5
  9. data/app/assets/javascripts/ab_admin/core/init.js.coffee +30 -15
  10. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +15 -7
  11. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +3 -0
  12. data/app/assets/javascripts/ab_admin/inputs/datetime_input.js.coffee +1 -1
  13. data/app/assets/stylesheets/ab_admin/application.css.scss +2 -1
  14. data/app/assets/stylesheets/ab_admin/components/_table_view.css.scss +12 -0
  15. data/app/controllers/admin/base_controller.rb +20 -2
  16. data/app/controllers/admin/manager_controller.rb +0 -2
  17. data/app/views/admin/base/create.js.erb +6 -0
  18. data/app/views/admin/base/edit.js.erb +10 -0
  19. data/app/views/admin/base/index.html.slim +2 -3
  20. data/app/views/admin/base/new.js.erb +8 -0
  21. data/app/views/admin/base/update.js.erb +7 -0
  22. data/app/views/admin/manager/_search_form.html.slim +1 -1
  23. data/app/views/admin/manager/_show_table.html.slim +7 -0
  24. data/app/views/admin/manager/_table.html.slim +6 -2
  25. data/app/views/admin/shared/_save_buttons.html.slim +1 -1
  26. data/features/dsl/action_items.feature +4 -4
  27. data/features/dsl/in_place_edit.feature +26 -0
  28. data/features/dsl/list_edit.feature +46 -0
  29. data/features/dsl/show.feature +37 -0
  30. data/features/step_definitions/dsl/in_place_edit_steps.rb +7 -0
  31. data/features/step_definitions/dsl/show_steps.rb +8 -0
  32. data/features/step_definitions/dsl/table_steps.rb +2 -2
  33. data/features/step_definitions/web_steps/browsing_steps.rb +13 -0
  34. data/features/support/paths.rb +1 -1
  35. data/lib/ab_admin/abstract_resource.rb +5 -1
  36. data/lib/ab_admin/config/base.rb +14 -0
  37. data/lib/ab_admin/version.rb +1 -1
  38. data/lib/ab_admin/views/admin_helpers.rb +22 -0
  39. data/lib/ab_admin/views/admin_navigation_helpers.rb +6 -7
  40. data/lib/ab_admin/views/form_builder.rb +1 -1
  41. data/lib/ab_admin/views/manager_helpers.rb +4 -0
  42. data/lib/ab_admin/views/search_form_builder.rb +5 -1
  43. data/lib/generators/template.rb +4 -3
  44. data/spec/dummy/app/helpers/application_helper.rb +1 -0
  45. data/spec/dummy/app/models/ab_admin/ab_admin_product.rb +33 -70
  46. data/spec/dummy/app/models/product.rb +2 -0
  47. data/vendor/assets/javascripts/jquery.hotkeys.js +106 -0
  48. metadata +26 -15
  49. data/NOTES +0 -16
  50. data/app/assets/images/admin/chosen-sprite.png +0 -0
  51. data/app/assets/stylesheets/ab_admin/chosen.css.scss +0 -368
  52. data/app/assets/stylesheets/ab_admin/components/_table_tools.css.scss +0 -94
  53. data/spec/dummy/app/models/.gitkeep +0 -0
  54. data/vendor/assets/javascripts/chosen.js.coffee +0 -780
@@ -1,780 +0,0 @@
1
- root = this
2
-
3
- class AbstractChosen
4
-
5
- constructor: (@form_field, @options={}) ->
6
- this.set_default_values()
7
-
8
- @is_multiple = @form_field.multiple
9
- this.set_default_text()
10
-
11
- this.setup()
12
-
13
- this.set_up_html()
14
- this.register_observers()
15
-
16
- this.finish_setup()
17
-
18
- set_default_values: ->
19
- @click_test_action = (evt) => this.test_active_click(evt)
20
- @activate_action = (evt) => this.activate_field(evt)
21
- @active_field = false
22
- @mouse_on_container = false
23
- @results_showing = false
24
- @result_highlighted = null
25
- @result_single_selected = null
26
- @allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]? and @form_field.options[0].text is "" then @options.allow_single_deselect else false
27
- @disable_search_threshold = @options.disable_search_threshold || 0
28
- @search_contains = @options.search_contains || false
29
- @choices = 0
30
- @single_backstroke_delete = @options.single_backstroke_delete || false
31
- @max_selected_options = @options.max_selected_options || Infinity
32
-
33
- set_default_text: ->
34
- if @form_field.getAttribute("data-placeholder")
35
- @default_text = @form_field.getAttribute("data-placeholder")
36
- else if @is_multiple
37
- @default_text = @options.placeholder_text_multiple || @options.placeholder_text || ""
38
- else
39
- @default_text = @options.placeholder_text_single || @options.placeholder_text || ""
40
-
41
- @results_none_found = @form_field.getAttribute("data-no_results_text") || @options.no_results_text || "Ничего не найдено"
42
-
43
- mouse_enter: -> @mouse_on_container = true
44
- mouse_leave: -> @mouse_on_container = false
45
-
46
- input_focus: (evt) ->
47
- setTimeout (=> this.container_mousedown()), 50 unless @active_field
48
-
49
- input_blur: (evt) ->
50
- if not @mouse_on_container
51
- @active_field = false
52
- setTimeout (=> this.blur_test()), 100
53
-
54
- result_add_option: (option) ->
55
- if not option.disabled
56
- option.dom_id = @container_id + "_o_" + option.array_index
57
-
58
- classes = if option.selected and @is_multiple then [] else ["active-result"]
59
- classes.push "result-selected" if option.selected
60
- classes.push "group-option" if option.group_array_index?
61
- classes.push option.classes if option.classes != ""
62
-
63
- style = if option.style.cssText != "" then " style=\"#{option.style}\"" else ""
64
-
65
- '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"'+style+'>' + option.html + '</li>'
66
- else
67
- ""
68
-
69
- results_update_field: ->
70
- this.results_reset_cleanup() if not @is_multiple
71
- this.result_clear_highlight()
72
- @result_single_selected = null
73
- this.results_build()
74
-
75
- results_toggle: ->
76
- if @results_showing
77
- this.results_hide()
78
- else
79
- this.results_show()
80
-
81
- remote_search: ->
82
- @data_cache ||= {}
83
- val = $.trim @search_field.attr('value')
84
- # log 'remote_search', val
85
- return false if val.length < 1 or val is @search_field.data('prevVal')
86
- @search_field.data('prevVal', val)
87
-
88
- @options.ajax.data ||= {}
89
- @options.ajax.data.q = val
90
- if @options.map
91
- pos = @options.map.getCenter()
92
- @options.ajax.data['with[lat]'] = pos.lat()
93
- @options.ajax.data['with[lon]'] = pos.lng()
94
-
95
- @options.ajax.success = (data) =>
96
- @form_field_jq.find('option').each -> $(this).remove() if not $(this).is(":selected")
97
- _.each data, (el) =>
98
- $("<option />").attr('value', el.id).html(el.name).appendTo(@form_field_jq).data('info', el.data)
99
-
100
- @keep_search_field = true
101
- @form_field_jq.trigger("liszt:updated")
102
- @keep_search_field = false
103
- @winnow_results()
104
- @data_cache[val] = data
105
-
106
- if @data_cache[val]
107
- @options.ajax.success(@data_cache[val])
108
- else
109
- $.ajax(@options.ajax)
110
-
111
- results_search: (evt) ->
112
- # log 'results_search'
113
- if @options.ajax
114
- @remote_search()
115
- else
116
- if @results_showing
117
- this.winnow_results()
118
- else
119
- this.results_show()
120
-
121
- keyup_checker: (evt) ->
122
- stroke = evt.which ? evt.keyCode
123
- this.search_field_scale()
124
-
125
- switch stroke
126
- when 8
127
- if @is_multiple and @backstroke_length < 1 and @choices > 0
128
- this.keydown_backstroke()
129
- else if not @pending_backstroke
130
- this.result_clear_highlight()
131
- this.results_search()
132
- when 13
133
- evt.preventDefault()
134
- this.result_select(evt) if this.results_showing
135
- when 27
136
- this.results_hide() if @results_showing
137
- return true
138
- when 9, 38, 40, 16, 91, 17
139
- # don't do anything on these keys
140
- else this.results_search()
141
-
142
- generate_field_id: ->
143
- new_id = this.generate_random_id()
144
- @form_field.id = new_id
145
- new_id
146
-
147
- generate_random_char: ->
148
- chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
149
- rand = Math.floor(Math.random() * chars.length)
150
- newchar = chars.substring rand, rand+1
151
-
152
- root.AbstractChosen = AbstractChosen
153
-
154
- class SelectParser
155
-
156
- constructor: ->
157
- @options_index = 0
158
- @parsed = []
159
-
160
- add_node: (child) ->
161
- if child.nodeName is "OPTGROUP"
162
- this.add_group child
163
- else
164
- this.add_option child
165
-
166
- add_group: (group) ->
167
- group_position = @parsed.length
168
- @parsed.push
169
- array_index: group_position
170
- group: true
171
- label: group.label
172
- children: 0
173
- disabled: group.disabled
174
- this.add_option( option, group_position, group.disabled ) for option in group.childNodes
175
-
176
- add_option: (option, group_position, group_disabled) ->
177
- if option.nodeName is "OPTION"
178
- if option.text != ""
179
- if group_position?
180
- @parsed[group_position].children += 1
181
- @parsed.push
182
- array_index: @parsed.length
183
- options_index: @options_index
184
- value: option.value
185
- text: option.text
186
- html: option.innerHTML
187
- selected: option.selected
188
- disabled: if group_disabled is true then group_disabled else option.disabled
189
- group_array_index: group_position
190
- classes: option.className
191
- style: option.style.cssText
192
- else
193
- @parsed.push
194
- array_index: @parsed.length
195
- options_index: @options_index
196
- empty: true
197
- @options_index += 1
198
-
199
- SelectParser.select_to_array = (select) ->
200
- parser = new SelectParser()
201
- parser.add_node( child ) for child in select.childNodes
202
- parser.parsed
203
-
204
- this.SelectParser = SelectParser
205
-
206
- root = this
207
- $ = jQuery
208
-
209
- $.fn.extend({
210
- chosen: (options) ->
211
- # Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
212
- return this if $.browser.msie and ($.browser.version is "6.0" or $.browser.version is "7.0")
213
- this.each((input_field) ->
214
- $this = $ this
215
- $this.data('chosen', new Chosen(this, options)) unless $this.hasClass "chzn-done"
216
- )
217
- })
218
-
219
-
220
-
221
- # jQuery CHOSEN ========================
222
- class Chosen extends AbstractChosen
223
-
224
- setup: ->
225
- @form_field_jq = $ @form_field
226
- @current_value = @form_field_jq.val()
227
- @is_rtl = @form_field_jq.hasClass "chzn-rtl"
228
-
229
- finish_setup: ->
230
- @form_field_jq.addClass "chzn-done"
231
-
232
- set_up_html: ->
233
- @container_id = if @form_field.id.length then @form_field.id.replace(/[^\w]/g, '_') else this.generate_field_id()
234
- @container_id += "_chzn"
235
-
236
- @f_width = @form_field_jq.outerWidth()
237
-
238
- container_div = ($ "<div />", {
239
- id: @container_id
240
- class: "chzn-container#{ if @is_rtl then ' chzn-rtl' else '' }"
241
- style: 'width: ' + (@f_width) + 'px;' #use parens around @f_width so coffeescript doesn't think + ' px' is a function parameter
242
- })
243
-
244
- if @is_multiple
245
- 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>'
246
- else
247
- container_div.html '<a href="javascript:void(0)" class="chzn-single chzn-default"><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>'
248
-
249
- @form_field_jq.hide().after container_div
250
- @container = ($ '#' + @container_id)
251
- @container.addClass( "chzn-container-" + (if @is_multiple then "multi" else "single") )
252
- @dropdown = @container.find('div.chzn-drop').first()
253
-
254
- dd_top = @container.height()
255
- dd_width = (@f_width - get_side_border_padding(@dropdown))
256
-
257
- @dropdown.css({"width": dd_width + "px", "top": dd_top + "px"})
258
-
259
- @search_field = @container.find('input').first()
260
- @search_results = @container.find('ul.chzn-results').first()
261
- this.search_field_scale()
262
-
263
- @search_no_results = @container.find('li.no-results').first()
264
-
265
- if @is_multiple
266
- @search_choices = @container.find('ul.chzn-choices').first()
267
- @search_container = @container.find('li.search-field').first()
268
- else
269
- @search_container = @container.find('div.chzn-search').first()
270
- @selected_item = @container.find('.chzn-single').first()
271
- sf_width = dd_width - get_side_border_padding(@search_container) - get_side_border_padding(@search_field)
272
- @search_field.css( {"width" : sf_width + "px"} )
273
-
274
- this.results_build()
275
- this.set_tab_index()
276
- @form_field_jq.trigger("liszt:ready", {chosen: this})
277
-
278
- register_observers: ->
279
- @container.mousedown (evt) => this.container_mousedown(evt)
280
- @container.mouseup (evt) => this.container_mouseup(evt)
281
- @container.mouseenter (evt) => this.mouse_enter(evt)
282
- @container.mouseleave (evt) => this.mouse_leave(evt)
283
-
284
- @search_results.mouseup (evt) => this.search_results_mouseup(evt)
285
- @search_results.mouseover (evt) => this.search_results_mouseover(evt)
286
- @search_results.mouseout (evt) => this.search_results_mouseout(evt)
287
-
288
- @form_field_jq.bind "liszt:updated", (evt) => this.results_update_field(evt)
289
-
290
- @search_field.blur (evt) => this.input_blur(evt)
291
- @search_field.keyup (evt) => this.keyup_checker(evt)
292
- @search_field.keydown (evt) => this.keydown_checker(evt)
293
-
294
- if @is_multiple
295
- @search_choices.click (evt) => this.choices_click(evt)
296
- @search_field.focus (evt) => this.input_focus(evt)
297
- else
298
- @container.click (evt) => evt.preventDefault() # gobble click of anchor
299
-
300
- search_field_disabled: ->
301
- @is_disabled = @form_field_jq[0].disabled
302
- if(@is_disabled)
303
- @container.addClass 'chzn-disabled'
304
- @search_field[0].disabled = true
305
- @selected_item.unbind "focus", @activate_action if !@is_multiple
306
- this.close_field()
307
- else
308
- @container.removeClass 'chzn-disabled'
309
- @search_field[0].disabled = false
310
- @selected_item.bind "focus", @activate_action if !@is_multiple
311
-
312
- container_mousedown: (evt) ->
313
- if !@is_disabled
314
- target_closelink = if evt? then ($ evt.target).hasClass "search-choice-close" else false
315
- if evt and evt.type is "mousedown" and not @results_showing
316
- evt.stopPropagation()
317
- if not @pending_destroy_click and not target_closelink
318
- if not @active_field
319
- @search_field.val "" if @is_multiple
320
- $(document).click @click_test_action
321
- this.results_show()
322
- else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chzn-single").length)
323
- evt.preventDefault()
324
- this.results_toggle()
325
-
326
- this.activate_field()
327
- else
328
- @pending_destroy_click = false
329
-
330
- container_mouseup: (evt) ->
331
- this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled
332
-
333
- blur_test: (evt) ->
334
- this.close_field() if not @active_field and @container.hasClass "chzn-container-active"
335
-
336
- close_field: ->
337
- $(document).unbind "click", @click_test_action
338
-
339
- if not @is_multiple
340
- @selected_item.attr "tabindex", @search_field.attr("tabindex")
341
- @search_field.attr "tabindex", -1
342
-
343
- @active_field = false
344
- this.results_hide()
345
-
346
- @container.removeClass "chzn-container-active"
347
- this.winnow_results_clear()
348
- this.clear_backstroke()
349
-
350
- this.show_search_field_default()
351
- this.search_field_scale()
352
-
353
- activate_field: ->
354
- if not @is_multiple and not @active_field
355
- @search_field.attr "tabindex", (@selected_item.attr "tabindex")
356
- @selected_item.attr "tabindex", -1
357
-
358
- @container.addClass "chzn-container-active"
359
- @active_field = true
360
-
361
- @search_field.val(@search_field.val())
362
- @search_field.focus()
363
-
364
-
365
- test_active_click: (evt) ->
366
- if $(evt.target).parents('#' + @container_id).length
367
- @active_field = true
368
- else
369
- this.close_field()
370
-
371
- results_build: ->
372
- # log 'results_build'
373
- @parsing = true
374
- @results_data = root.SelectParser.select_to_array @form_field
375
-
376
- if @is_multiple and @choices > 0
377
- @search_choices.find("li.search-choice").remove()
378
- @choices = 0
379
- else if not @is_multiple
380
- @selected_item.addClass("chzn-default").find("span").text(@default_text)
381
- if @form_field.options.length <= @disable_search_threshold
382
- @container.addClass "chzn-container-single-nosearch"
383
- else
384
- @container.removeClass "chzn-container-single-nosearch"
385
-
386
- content = ''
387
- for data in @results_data
388
- if data.group
389
- content += this.result_add_group data
390
- else if !data.empty
391
- content += this.result_add_option data
392
- if data.selected and @is_multiple
393
- this.choice_build data
394
- else if data.selected and not @is_multiple
395
- @selected_item.removeClass("chzn-default").find("span").text data.text
396
- this.single_deselect_control_build() if @allow_single_deselect
397
-
398
- this.search_field_disabled()
399
- this.show_search_field_default()
400
- this.search_field_scale()
401
-
402
- @search_results.html content
403
- @parsing = false
404
-
405
-
406
- result_add_group: (group) ->
407
- if not group.disabled
408
- group.dom_id = @container_id + "_g_" + group.array_index
409
- '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>'
410
- else
411
- ""
412
-
413
- result_do_highlight: (el) ->
414
- if el.length
415
- this.result_clear_highlight()
416
-
417
- @result_highlight = el
418
- @result_highlight.addClass "highlighted"
419
-
420
- maxHeight = parseInt @search_results.css("maxHeight"), 10
421
- visible_top = @search_results.scrollTop()
422
- visible_bottom = maxHeight + visible_top
423
-
424
- high_top = @result_highlight.position().top + @search_results.scrollTop()
425
- high_bottom = high_top + @result_highlight.outerHeight()
426
-
427
- if high_bottom >= visible_bottom
428
- @search_results.scrollTop if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
429
- else if high_top < visible_top
430
- @search_results.scrollTop high_top
431
-
432
- result_clear_highlight: ->
433
- @result_highlight.removeClass "highlighted" if @result_highlight
434
- @result_highlight = null
435
-
436
- results_show: ->
437
- if not @is_multiple
438
- @selected_item.addClass "chzn-single-with-drop"
439
- if @result_single_selected
440
- this.result_do_highlight( @result_single_selected )
441
- else if @max_selected_options <= @choices
442
- @form_field_jq.trigger("liszt:maxselected", {chosen: this})
443
- return false
444
-
445
- dd_top = if @is_multiple then @container.height() else (@container.height() - 1)
446
- @form_field_jq.trigger("liszt:showing_dropdown", {chosen: this})
447
- @dropdown.css {"top": dd_top + "px", "left":0}
448
- @results_showing = true
449
-
450
- @search_field.focus()
451
- @search_field.val @search_field.val()
452
-
453
- this.winnow_results()
454
-
455
- results_hide: ->
456
- @selected_item.removeClass "chzn-single-with-drop" unless @is_multiple
457
- this.result_clear_highlight()
458
- @form_field_jq.trigger("liszt:hiding_dropdown", {chosen: this})
459
- @dropdown.css {"left":"-9000px"}
460
- @results_showing = false
461
-
462
-
463
- set_tab_index: (el) ->
464
- if @form_field_jq.attr "tabindex"
465
- ti = @form_field_jq.attr "tabindex"
466
- @form_field_jq.attr "tabindex", -1
467
-
468
- if @is_multiple
469
- @search_field.attr "tabindex", ti
470
- else
471
- @selected_item.attr "tabindex", ti
472
- @search_field.attr "tabindex", -1
473
-
474
- show_search_field_default: ->
475
- return if @keep_search_field
476
- if @is_multiple and @choices < 1 and not @active_field
477
- @search_field.val(@default_text)
478
- @search_field.addClass "default"
479
- else
480
- @search_field.val("")
481
- @search_field.removeClass "default"
482
-
483
- search_results_mouseup: (evt) ->
484
- target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
485
- if target.length
486
- @result_highlight = target
487
- this.result_select(evt)
488
-
489
- search_results_mouseover: (evt) ->
490
- target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
491
- this.result_do_highlight( target ) if target
492
-
493
- search_results_mouseout: (evt) ->
494
- this.result_clear_highlight() if $(evt.target).hasClass "active-result" or $(evt.target).parents('.active-result').first()
495
-
496
-
497
- choices_click: (evt) ->
498
- evt.preventDefault()
499
- if( @active_field and not($(evt.target).hasClass "search-choice" or $(evt.target).parents('.search-choice').first) and not @results_showing )
500
- this.results_show()
501
-
502
- choice_build: (item) ->
503
- if @is_multiple and @max_selected_options <= @choices
504
- @form_field_jq.trigger("liszt:maxselected", {chosen: this})
505
- return false # fire event
506
- choice_id = @container_id + "_c_" + item.array_index
507
- @choices += 1
508
- @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>'
509
- link = $('#' + choice_id).find("a").first()
510
- link.click (evt) => this.choice_destroy_link_click(evt)
511
-
512
- choice_destroy_link_click: (evt) ->
513
- evt.preventDefault()
514
- if not @is_disabled
515
- @pending_destroy_click = true
516
- this.choice_destroy $(evt.target)
517
- else
518
- evt.stopPropagation
519
-
520
- choice_destroy: (link) ->
521
- @choices -= 1
522
- this.show_search_field_default()
523
-
524
- this.results_hide() if @is_multiple and @choices > 0 and @search_field.val().length < 1
525
-
526
- this.result_deselect (link.attr "rel")
527
- link.parents('li').first().remove()
528
-
529
- results_reset: ->
530
- @form_field.options[0].selected = true
531
- @selected_item.find("span").text @default_text
532
- @selected_item.addClass("chzn-default") if not @is_multiple
533
- this.show_search_field_default()
534
- this.results_reset_cleanup()
535
- @form_field_jq.trigger "change"
536
- this.results_hide() if @active_field
537
-
538
- results_reset_cleanup: ->
539
- @selected_item.find("abbr").remove()
540
-
541
- result_select: (evt) ->
542
- if @result_highlight
543
- high = @result_highlight
544
- high_id = high.attr "id"
545
-
546
- this.result_clear_highlight()
547
-
548
- if @is_multiple
549
- this.result_deactivate high
550
- else
551
- @search_results.find(".result-selected").removeClass "result-selected"
552
- @result_single_selected = high
553
- @selected_item.removeClass("chzn-default")
554
-
555
- high.addClass "result-selected"
556
-
557
- position = high_id.substr(high_id.lastIndexOf("_") + 1 )
558
- item = @results_data[position]
559
- item.selected = true
560
-
561
- @form_field.options[item.options_index].selected = true
562
-
563
- if @is_multiple
564
- this.choice_build item
565
- else
566
- @selected_item.find("span").first().text item.text
567
- this.single_deselect_control_build() if @allow_single_deselect
568
-
569
- this.results_hide() unless evt.metaKey and @is_multiple
570
-
571
- @search_field.val ""
572
-
573
- @form_field_jq.trigger "change", {'selected': @form_field.options[item.options_index].value} if @is_multiple || @form_field_jq.val() != @current_value
574
- @current_value = @form_field_jq.val()
575
- this.search_field_scale()
576
-
577
- result_activate: (el) ->
578
- el.addClass("active-result")
579
-
580
- result_deactivate: (el) ->
581
- el.removeClass("active-result")
582
-
583
- result_deselect: (pos) ->
584
- result_data = @results_data[pos]
585
- result_data.selected = false
586
-
587
- @form_field.options[result_data.options_index].selected = false
588
- result = $("#" + @container_id + "_o_" + pos)
589
- result.removeClass("result-selected").addClass("active-result").show()
590
-
591
- this.result_clear_highlight()
592
- this.winnow_results()
593
-
594
- @form_field_jq.trigger "change", {deselected: @form_field.options[result_data.options_index].value}
595
- this.search_field_scale()
596
-
597
- single_deselect_control_build: ->
598
- @selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" if @allow_single_deselect and @selected_item.find("abbr").length < 1
599
-
600
- winnow_results: ->
601
- # log 'winnow_results'
602
- # return if window.skip_winnow_results
603
- this.no_results_clear()
604
-
605
- results = 0
606
-
607
- searchText = if @search_field.val() is @default_text then "" else $('<div/>').text($.trim(@search_field.val())).html()
608
- regexAnchor = if @search_contains then "" else "^"
609
- regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
610
- zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i')
611
-
612
- # log 'searchText', searchText
613
- # log 'results_data', @results_data[1]?.html
614
- for option in @results_data
615
- if not option.disabled and not option.empty
616
- if option.group
617
- $('#' + option.dom_id).css('display', 'none')
618
- else if not (@is_multiple and option.selected)
619
- found = false
620
- result_id = option.dom_id
621
- result = $("#" + result_id)
622
-
623
- if regex.test option.html
624
- found = true
625
- results += 1
626
- else if !@options.no_word_start_search and (option.html.indexOf(" ") >= 0 or option.html.indexOf("[") == 0)
627
- #TODO: replace this substitution of /\[\]/ with a list of characters to skip.
628
- parts = option.html.replace(/\[|\]/g, "").split(" ")
629
- if parts.length
630
- for part in parts
631
- if regex.test part
632
- found = true
633
- results += 1
634
-
635
- if found
636
- if searchText.length
637
- startpos = option.html.search zregex
638
- text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length)
639
- text = text.substr(0, startpos) + '<em>' + text.substr(startpos)
640
- else
641
- text = option.html
642
-
643
- result.html(text)
644
- this.result_activate result
645
-
646
- $("#" + @results_data[option.group_array_index].dom_id).css('display', 'list-item') if option.group_array_index?
647
- else
648
- this.result_clear_highlight() if @result_highlight and result_id is @result_highlight.attr 'id'
649
- this.result_deactivate result
650
-
651
- if results < 1 and searchText.length
652
- this.no_results searchText
653
- else
654
- this.winnow_results_set_highlight()
655
-
656
- winnow_results_clear: ->
657
- @search_field.val ""
658
- lis = @search_results.find("li")
659
-
660
- for li in lis
661
- li = $(li)
662
- if li.hasClass "group-result"
663
- li.css('display', 'auto')
664
- else if not @is_multiple or not li.hasClass "result-selected"
665
- this.result_activate li
666
-
667
- winnow_results_set_highlight: ->
668
- if not @result_highlight
669
-
670
- selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
671
- do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
672
-
673
- this.result_do_highlight do_high if do_high?
674
-
675
- no_results: (terms) ->
676
- no_results_html = $('<li class="no-results">' + @results_none_found + ' "<span></span>"</li>')
677
- no_results_html.find("span").first().html(terms)
678
-
679
- @search_results.append no_results_html
680
-
681
- no_results_clear: ->
682
- @search_results.find(".no-results").remove()
683
-
684
- keydown_arrow: ->
685
- if not @result_highlight
686
- first_active = @search_results.find("li.active-result").first()
687
- this.result_do_highlight $(first_active) if first_active
688
- else if @results_showing
689
- next_sib = @result_highlight.nextAll("li.active-result").first()
690
- this.result_do_highlight next_sib if next_sib
691
- this.results_show() if not @results_showing
692
-
693
- keyup_arrow: ->
694
- if not @results_showing and not @is_multiple
695
- this.results_show()
696
- else if @result_highlight
697
- prev_sibs = @result_highlight.prevAll("li.active-result")
698
-
699
- if prev_sibs.length
700
- this.result_do_highlight prev_sibs.first()
701
- else
702
- this.results_hide() if @choices > 0
703
- this.result_clear_highlight()
704
-
705
- keydown_backstroke: ->
706
- if @pending_backstroke
707
- this.choice_destroy @pending_backstroke.find("a").first()
708
- this.clear_backstroke()
709
- else
710
- @pending_backstroke = @search_container.siblings("li.search-choice").last()
711
- if @single_backstroke_delete
712
- @keydown_backstroke()
713
- else
714
- @pending_backstroke.addClass "search-choice-focus"
715
-
716
- clear_backstroke: ->
717
- @pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke
718
- @pending_backstroke = null
719
-
720
- keydown_checker: (evt) ->
721
- stroke = evt.which ? evt.keyCode
722
- this.search_field_scale()
723
-
724
- this.clear_backstroke() if stroke != 8 and this.pending_backstroke
725
-
726
- switch stroke
727
- when 8
728
- @backstroke_length = this.search_field.val().length
729
- break
730
- when 9
731
- this.result_select(evt) if this.results_showing and not @is_multiple
732
- @mouse_on_container = false
733
- break
734
- when 13
735
- evt.preventDefault()
736
- break
737
- when 38
738
- evt.preventDefault()
739
- this.keyup_arrow()
740
- break
741
- when 40
742
- this.keydown_arrow()
743
- break
744
-
745
- search_field_scale: ->
746
- if @is_multiple
747
- h = 0
748
- w = 0
749
-
750
- style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"
751
- styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing']
752
-
753
- for style in styles
754
- style_block += style + ":" + @search_field.css(style) + ";"
755
-
756
- div = $('<div />', { 'style' : style_block })
757
- div.text @search_field.val()
758
- $('body').append div
759
-
760
- w = div.width() + 25
761
- div.remove()
762
-
763
- if( w > @f_width-10 )
764
- w = @f_width - 10
765
-
766
- @search_field.css({'width': w + 'px'})
767
-
768
- dd_top = @container.height()
769
- @dropdown.css({"top": dd_top + "px"})
770
-
771
- generate_random_id: ->
772
- string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char()
773
- while $("#" + string).length > 0
774
- string += this.generate_random_char()
775
- string
776
-
777
- get_side_border_padding = (elmt) ->
778
- side_border_padding = elmt.outerWidth() - elmt.width()
779
-
780
- root.get_side_border_padding = get_side_border_padding