ab_admin 0.1.0 → 0.1.1

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