wice_grid 3.0.0.pre1

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 (64) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +412 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +1179 -0
  5. data/Rakefile +42 -0
  6. data/SAVED_QUERIES_HOWTO.rdoc +123 -0
  7. data/VERSION +1 -0
  8. data/lib/generators/wice_grid/templates/calendarview.css +107 -0
  9. data/lib/generators/wice_grid/templates/calendarview.js +1168 -0
  10. data/lib/generators/wice_grid/templates/icons/arrow_down.gif +0 -0
  11. data/lib/generators/wice_grid/templates/icons/arrow_up.gif +0 -0
  12. data/lib/generators/wice_grid/templates/icons/calendar_view_month.png +0 -0
  13. data/lib/generators/wice_grid/templates/icons/delete.png +0 -0
  14. data/lib/generators/wice_grid/templates/icons/expand.png +0 -0
  15. data/lib/generators/wice_grid/templates/icons/page_white_excel.png +0 -0
  16. data/lib/generators/wice_grid/templates/icons/page_white_find.png +0 -0
  17. data/lib/generators/wice_grid/templates/icons/table.png +0 -0
  18. data/lib/generators/wice_grid/templates/icons/table_refresh.png +0 -0
  19. data/lib/generators/wice_grid/templates/icons/tick_all.png +0 -0
  20. data/lib/generators/wice_grid/templates/icons/untick_all.png +0 -0
  21. data/lib/generators/wice_grid/templates/wice_grid.css +173 -0
  22. data/lib/generators/wice_grid/templates/wice_grid.yml +279 -0
  23. data/lib/generators/wice_grid/templates/wice_grid_config.rb +154 -0
  24. data/lib/generators/wice_grid/templates/wice_grid_jquery.js +161 -0
  25. data/lib/generators/wice_grid/templates/wice_grid_prototype.js +153 -0
  26. data/lib/generators/wice_grid/wice_grid_assets_jquery_generator.rb +32 -0
  27. data/lib/generators/wice_grid/wice_grid_assets_prototype_generator.rb +34 -0
  28. data/lib/grid_output_buffer.rb +52 -0
  29. data/lib/grid_renderer.rb +535 -0
  30. data/lib/helpers/js_calendar_helpers.rb +183 -0
  31. data/lib/helpers/wice_grid_misc_view_helpers.rb +113 -0
  32. data/lib/helpers/wice_grid_serialized_queries_view_helpers.rb +91 -0
  33. data/lib/helpers/wice_grid_view_helpers.rb +781 -0
  34. data/lib/js_adaptors/jquery_adaptor.rb +145 -0
  35. data/lib/js_adaptors/js_adaptor.rb +12 -0
  36. data/lib/js_adaptors/prototype_adaptor.rb +168 -0
  37. data/lib/table_column_matrix.rb +51 -0
  38. data/lib/tasks/wice_grid_tasks.rake +28 -0
  39. data/lib/view_columns.rb +486 -0
  40. data/lib/views/create.rjs +13 -0
  41. data/lib/views/create_jq.rjs +31 -0
  42. data/lib/views/delete.rjs +12 -0
  43. data/lib/views/delete_jq.rjs +26 -0
  44. data/lib/wice_grid.rb +827 -0
  45. data/lib/wice_grid_controller.rb +165 -0
  46. data/lib/wice_grid_core_ext.rb +179 -0
  47. data/lib/wice_grid_misc.rb +98 -0
  48. data/lib/wice_grid_serialized_queries_controller.rb +86 -0
  49. data/lib/wice_grid_serialized_query.rb +15 -0
  50. data/lib/wice_grid_spreadsheet.rb +33 -0
  51. data/test/.gitignore +2 -0
  52. data/test/database.yml +21 -0
  53. data/test/schema.rb +33 -0
  54. data/test/test_helper.rb +89 -0
  55. data/test/views/projects_and_people_grid.html.erb +12 -0
  56. data/test/views/projects_and_people_grid_invalid.html.erb +12 -0
  57. data/test/views/simple_projects_grid.html.erb +9 -0
  58. data/test/wice_grid_core_ext_test.rb +183 -0
  59. data/test/wice_grid_functional_test.rb +68 -0
  60. data/test/wice_grid_misc_test.rb +41 -0
  61. data/test/wice_grid_test.rb +42 -0
  62. data/test/wice_grid_view_helper_test.rb +12 -0
  63. data/wice_grid.gemspec +111 -0
  64. metadata +153 -0
@@ -0,0 +1,145 @@
1
+ # encoding: UTF-8
2
+ module Wice::JsAdaptor #:nodoc:
3
+
4
+ module Jquery #:nodoc:
5
+
6
+ def self.included(base) #:nodoc:
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods #:nodoc:
11
+
12
+ def init #:nodoc:
13
+ end
14
+
15
+ def dom_loaded #:nodoc:
16
+ %/$(document).ready(function(){\n/
17
+ end
18
+
19
+ def reset_button_initialization(grid_name, reset_grid_javascript) #:nodoc:
20
+ %/ $('div##{grid_name}.wice_grid_container .reset').click(function(e){\n/+
21
+ %/ #{reset_grid_javascript};\n/+
22
+ %/ });\n/
23
+ end
24
+
25
+ def submit_button_initialization(grid_name, submit_grid_javascript) #:nodoc:
26
+ %/ $('div##{grid_name}.wice_grid_container .submit').click(function(e){\n/+
27
+ %/ #{submit_grid_javascript};\n/+
28
+ %/ });\n/
29
+ end
30
+
31
+ def show_hide_button_initialization(grid_name, filter_row_id) #:nodoc:
32
+ %/ $('##{grid_name}_show_icon').click(function(){\n/+
33
+ %/ $('##{grid_name}_show_icon').hide();\n/+
34
+ %/ $('##{grid_name}_hide_icon').show();\n/+
35
+ %/ $('##{filter_row_id}').show();\n/+
36
+ %/ })\n/+
37
+ %/ $('##{grid_name}_hide_icon').click(function(){\n/+
38
+ %/ $('##{grid_name}_show_icon').show();\n/+
39
+ %/ $('##{grid_name}_hide_icon').hide();\n/+
40
+ %/ $('##{filter_row_id}').hide();\n/+
41
+ %/ });\n/
42
+ end
43
+
44
+ def enter_key_event_registration(grid_name) #:nodoc:
45
+ %! $('div##{grid_name}.wice_grid_container .wice_grid_filter_row input[type=text]').keydown(function(event){\n! +
46
+ %! if (event.keyCode == 13) {#{grid_name}.process()}\n! +
47
+ %! });\n!
48
+ end
49
+
50
+ def csv_export_icon_initialization(grid_name) #:nodoc:
51
+ %! $('div##{grid_name}.wice_grid_container .export_to_csv_button').click(function(e){\n! +
52
+ %! #{grid_name}.export_to_csv()\n! +
53
+ %! });\n!
54
+ end
55
+
56
+ def auto_reloading_selects_event_initialization(grid_name) #:nodoc:
57
+ %! $('div##{grid_name}.wice_grid_container select.auto_reload, .#{grid_name}_detached_filter select.auto_reload').change(function(e){\n! +
58
+ %! #{grid_name}.process()\n! +
59
+ %! });\n!
60
+ end
61
+
62
+ def auto_reloading_inputs_event_initialization(grid_name) #:nodoc:
63
+ %! $('div##{grid_name}.wice_grid_container input.auto_reload, .#{grid_name}_detached_filter input.auto_reload').keyup(function(event, element){\n! +
64
+ %! #{grid_name}.process(this.id);\n! +
65
+ %! });\n!
66
+ end
67
+
68
+ def auto_reloading_inputs_with_negation_checkboxes_event_initialization(grid_name) #:nodoc:
69
+ %! $('div##{grid_name}.wice_grid_container input.negation_checkbox, .#{grid_name}_detached_filter input.negation_checkbox').click(function(event, element){\n! +
70
+ %! #{grid_name}.process(this.id);\n! +
71
+ %! });\n!
72
+ end
73
+
74
+
75
+ def auto_reloading_calendar_event_initialization(grid_name) #:nodoc:
76
+ %! $(document).bind('wg:calendarChanged', function(event){\n! +
77
+ %! #{grid_name}.process()\n! +
78
+ %! });\n!
79
+ end
80
+
81
+ def show_all_link_initialization(grid_name, confirmation, parameters_json) #:nodoc:
82
+ %/ $('div##{grid_name}.wice_grid_container .show_all_link').click(function(e){ \n/ +
83
+ %/ #{confirmation} #{grid_name}.reload_page_for_given_grid_state(#{parameters_json}) \n/ +
84
+ %/})\n/
85
+ end
86
+
87
+ def back_to_pagination_link_initialization(grid_name, parameters_json) #:nodoc:
88
+ %/ $('div##{grid_name}.wice_grid_container .show_all_link').click(function(e){\n/ +
89
+ %/ #{grid_name}.reload_page_for_given_grid_state(#{parameters_json})\n/ +
90
+ %/ })\n/
91
+ end
92
+
93
+ def call_to_save_query_and_key_event_initialization_for_saving_queries(
94
+ id_and_name, grid_name, base_path_to_query_controller, parameters_json, ids_json) #:nodoc:
95
+ %/ function #{grid_name}_save_query(){\n/ +
96
+ %` if ( typeof(#{grid_name}) != "undefined")\n` +
97
+ %! #{grid_name}.save_query($('##{id_and_name}')[0].value, '#{base_path_to_query_controller}', #{parameters_json}, #{ids_json})\n! +
98
+ %/}\n/ +
99
+ %/ $('##{id_and_name}').keydown(function(event){\n/ +
100
+ %/ if (event.keyCode == 13) #{grid_name}_save_query();\n/ +
101
+ %/ })\n/
102
+ end
103
+
104
+ def js_framework_specific_calendar_assets(view) #:nodoc:
105
+ ''
106
+ end
107
+
108
+ def js_framework_specific_calendar_js_name #:nodoc:
109
+ nil
110
+ end
111
+
112
+ def js_framework_specific_calendar_css_name #:nodoc:
113
+ nil
114
+ end
115
+
116
+ def action_column_initialization(grid_name) #:nodoc:
117
+ %! $('div##{grid_name}.wice_grid_container .select_all').click(function(e){\n! +
118
+ %! $('div##{grid_name}.wice_grid_container .sel input').each(function(i, checkbox){\n! +
119
+ %! checkbox.checked = true;\n! +
120
+ %! })\n! +
121
+ %! })\n! +
122
+ %! $('div##{grid_name}.wice_grid_container .deselect_all').click(function(e){\n! +
123
+ %! $('div##{grid_name}.wice_grid_container .sel input').each(function(i, checkbox){\n! +
124
+ %! checkbox.checked = false;\n! +
125
+ %! })\n! +
126
+ %! })\n!
127
+ end
128
+
129
+ def fade_this(notification_messages_id) #:nodoc:
130
+ "$('##{notification_messages_id}').effect('fade')"
131
+ end
132
+
133
+ def focus_element(element_to_focus) #:nodoc:
134
+ %! var elements = $('##{element_to_focus}');\n! +
135
+ %! if (elements[0]){\n! +
136
+ %! var elToFocus = elements[0];\n! +
137
+ %! elToFocus.value = elToFocus.value;\n! + # this will just place the cursor at the end of the text input
138
+ %! elToFocus.focus();\n! +
139
+ %! }\n!
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ module Wice::JsAdaptor #:nodoc:
4
+ mattr_accessor :calendar_module
5
+ def self.init #:nodoc:
6
+ if Wice::Defaults::JS_FRAMEWORK == :prototype
7
+ include Wice::JsAdaptor::Prototype
8
+ else
9
+ include Wice::JsAdaptor::Jquery
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,168 @@
1
+ # encoding: UTF-8
2
+ module Wice::JsAdaptor #:nodoc:
3
+
4
+ module Prototype #:nodoc:
5
+
6
+ def self.included(base) #:nodoc:
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods #:nodoc:
11
+ def init #:nodoc:
12
+ end
13
+
14
+ def dom_loaded #:nodoc:
15
+ %/ document.observe("dom:loaded", function() {\n/
16
+ end
17
+
18
+ def reset_button_initialization(grid_name, reset_grid_javascript) #:nodoc:
19
+ %/ $$('div##{grid_name}.wice_grid_container .reset').each(function(e){\n/+
20
+ %/ e.observe('click', function(){\n/+
21
+ %/ #{reset_grid_javascript};\n/+
22
+ %/ })\n/+
23
+ %/ });\n/
24
+ end
25
+
26
+ def submit_button_initialization(grid_name, submit_grid_javascript) #:nodoc:
27
+ %/ $$('div##{grid_name}.wice_grid_container .submit').each(function(e){\n/+
28
+ %/ e.observe('click', function(){\n/+
29
+ %/ #{submit_grid_javascript};\n/+
30
+ %/ })\n/+
31
+ %/ });\n/
32
+ end
33
+
34
+ def show_hide_button_initialization(grid_name, filter_row_id) #:nodoc:
35
+ %/ $('#{grid_name}_show_icon').observe('click', function(){\n/+
36
+ %/ Element.toggle('#{grid_name}_show_icon');\n/+
37
+ %/ Element.toggle('#{grid_name}_hide_icon');\n/+
38
+ %/ $('#{filter_row_id}').show();\n/+
39
+ %/ })\n/+
40
+ %/ $('#{grid_name}_hide_icon').observe('click', function(){\n/+
41
+ %/ Element.toggle('#{grid_name}_show_icon');\n/+
42
+ %/ Element.toggle('#{grid_name}_hide_icon');\n/+
43
+ %/ $('#{filter_row_id}').hide();\n/+
44
+ %/ });\n/
45
+ end
46
+
47
+ def enter_key_event_registration(grid_name) #:nodoc:
48
+ %! $$('div##{grid_name}.wice_grid_container .wice_grid_filter_row input[type=text]').each(function(e){\n! +
49
+ %! e.observe('keydown', function(event){\n! +
50
+ %! if (event.keyCode == 13) {#{grid_name}.process()}\n! +
51
+ %! })\n! +
52
+ %! });\n!
53
+ end
54
+
55
+ def csv_export_icon_initialization(grid_name) #:nodoc:
56
+ %! $$('div##{grid_name}.wice_grid_container .export_to_csv_button').each(function(e){\n! +
57
+ %! e.observe('click', function(event){\n! +
58
+ %! #{grid_name}.export_to_csv()\n! +
59
+ %! })\n! +
60
+ %! });\n!
61
+ end
62
+
63
+ def auto_reloading_selects_event_initialization(grid_name) #:nodoc:
64
+ %! $$('div##{grid_name}.wice_grid_container select.auto_reload', '.#{grid_name}_detached_filter select.auto_reload').each(function(e){\n! +
65
+ %! e.observe('change', function(event){\n! +
66
+ %! #{grid_name}.process()\n! +
67
+ %! })\n! +
68
+ %! });\n!
69
+ end
70
+
71
+ def auto_reloading_inputs_event_initialization(grid_name) #:nodoc:
72
+ %! $$('div##{grid_name}.wice_grid_container input.auto_reload', '.#{grid_name}_detached_filter input.auto_reload').each(function(e){\n! +
73
+ %! e.observe('keyup', function(event){\n! +
74
+ %! #{grid_name}.process(event.element().id)\n! +
75
+ %! })\n! +
76
+ %! });\n!
77
+ end
78
+
79
+ def auto_reloading_inputs_with_negation_checkboxes_event_initialization(grid_name) #:nodoc:
80
+ %! $$('div##{grid_name}.wice_grid_container input.negation_checkbox', '.#{grid_name}_detached_filter input.negation_checkbox').each(function(e){\n! +
81
+ %! e.observe('click', function(event){\n! +
82
+ %! #{grid_name}.process(event.element().id)\n! +
83
+ %! })\n! +
84
+ %! });\n!
85
+ end
86
+
87
+
88
+ def auto_reloading_calendar_event_initialization(grid_name) #:nodoc:
89
+ %! document.observe('wg:calendarChanged', function(event){\n! +
90
+ %! #{grid_name}.process()\n! +
91
+ %! });\n!
92
+ end
93
+
94
+
95
+ def show_all_link_initialization(grid_name, confirmation, parameters_json) #:nodoc:
96
+ %/ $$('div##{grid_name}.wice_grid_container .show_all_link').each(function(e){\n/ +
97
+ %/ e.observe('click', function(){\n/ +
98
+ %/ #{confirmation} #{grid_name}.reload_page_for_given_grid_state(#{parameters_json})\n/ +
99
+ %/ })\n/ +
100
+ %/ })\n/
101
+ end
102
+
103
+
104
+ def back_to_pagination_link_initialization(grid_name, parameters_json) #:nodoc:
105
+ %/ $$('div##{grid_name}.wice_grid_container .show_all_link').each(function(e){\n/ +
106
+ %/ e.observe('click', function(){\n/ +
107
+ %/ #{grid_name}.reload_page_for_given_grid_state(#{parameters_json})\n/ +
108
+ %/ })\n/ +
109
+ %/ })\n/
110
+ end
111
+
112
+ def call_to_save_query_and_key_event_initialization_for_saving_queries(
113
+ id_and_name, grid_name, base_path_to_query_controller, parameters_json, ids_json) #:nodoc:
114
+ %/ function #{grid_name}_save_query(){\n/ +
115
+ %` if ( typeof(#{grid_name}) != "undefined")\n` +
116
+ %/ #{grid_name}.save_query($F('#{id_and_name}'), '#{base_path_to_query_controller}', #{parameters_json}, #{ids_json})\n/ +
117
+ %/ }\n/ +
118
+ %/ $('#{id_and_name}').observe('keydown', function(event){\n/ +
119
+ %/ if (event.keyCode == 13) #{grid_name}_save_query();\n/ +
120
+ %/ })\n/
121
+ end
122
+
123
+
124
+ def js_framework_specific_calendar_assets(view) #:nodoc:
125
+ view.stylesheet_link_tag("calendarview.css") + view.javascript_include_tag("calendarview.js")
126
+ end
127
+
128
+ def js_framework_specific_calendar_js_name #:nodoc:
129
+ 'calendarview.js'
130
+ end
131
+
132
+ def js_framework_specific_calendar_css_name #:nodoc:
133
+ 'calendarview.css'
134
+ end
135
+
136
+
137
+ def action_column_initialization(grid_name) #:nodoc:
138
+ %! $$('div##{grid_name}.wice_grid_container .select_all').each(function(e){\n! +
139
+ %! e.observe('click', function(){\n! +
140
+ %! $$('div##{grid_name}.wice_grid_container .sel input').each(function(checkbox){\n! +
141
+ %! checkbox.checked = true;\n! +
142
+ %! })\n! +
143
+ %! })\n! +
144
+ %! })\n! +
145
+ %! $$('div##{grid_name}.wice_grid_container .deselect_all').each(function(e){\n! +
146
+ %! e.observe('click', function(){\n! +
147
+ %! $$('div##{grid_name}.wice_grid_container .sel input').each(function(checkbox){\n! +
148
+ %! checkbox.checked = false;\n! +
149
+ %! })\n! +
150
+ %! })\n! +
151
+ %! })\n!
152
+ end
153
+
154
+ def fade_this(notification_messages_id) #:nodoc:
155
+ "new Effect.Fade(this)"
156
+ end
157
+
158
+ def focus_element(element_to_focus) #:nodoc:
159
+ %! var elToFocus = $('#{element_to_focus}');\n! +
160
+ %! elToFocus.focus();\n! +
161
+ %! elToFocus.value = elToFocus.value;\n! # this will just place the cursor at the end of the text input
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+
168
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+ module Wice
3
+ class TableColumnMatrix < Hash #:nodoc:
4
+
5
+ attr_reader :generated_conditions
6
+
7
+ def initialize() #:nodoc:
8
+ super
9
+ @generated_conditions = []
10
+ @by_table_names = HashWithIndifferentAccess.new
11
+ end
12
+
13
+ def add_condition(column, conditions)
14
+ @generated_conditions << [column, conditions] unless conditions.blank?
15
+ end
16
+
17
+ def conditions
18
+ @generated_conditions.collect{|_, cond| cond}
19
+ end
20
+
21
+ alias_method :get, :[]
22
+
23
+ attr_reader :default_model_class
24
+ def default_model_class=(model_klass) #:nodoc:
25
+ init_columns_of_table(model_klass) unless has_key?(model_klass)
26
+ @default_model_class = model_klass
27
+ end
28
+
29
+ def [](model_klass) #:nodoc:
30
+ init_columns_of_table(model_klass) unless has_key?(model_klass)
31
+ get(model_klass)
32
+ end
33
+
34
+ def get_column_by_model_class_and_column_name(model_class, column_name) #:nodoc:
35
+ self[model_class][column_name]
36
+ end
37
+
38
+ def get_column_in_default_model_class_by_column_name(column_name) #:nodoc:
39
+ raise WiceGridException.new("Cannot search for a column in a default model as the default model is not set") if @default_model_class.nil?
40
+ self[@default_model_class][column_name]
41
+ end
42
+
43
+ def init_columns_of_table(model_klass) #:nodoc:
44
+ self[model_klass] = HashWithIndifferentAccess.new(model_klass.columns.index_by(&:name))
45
+ @by_table_names[model_klass.table_name] = self[model_klass]
46
+ self[model_klass].each_value{|c| c.model_klass = model_klass}
47
+ end
48
+ alias_method :<< , :init_columns_of_table
49
+
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ namespace "wice_grid" do
2
+
3
+ desc "Create a table to store saved queries"
4
+ task :create_queries_table => :environment do
5
+
6
+ class CreateWiceGridSerializedQueriesTable < ::ActiveRecord::Migration
7
+ def self.up
8
+ create_table :wice_grid_serialized_queries do |t|
9
+ t.column :name, :string
10
+ t.column :grid_name, :string
11
+ t.column :query, :text
12
+
13
+ t.timestamps
14
+ end
15
+ add_index :wice_grid_serialized_queries, :grid_name
16
+ add_index :wice_grid_serialized_queries, [:grid_name, :id]
17
+ end
18
+
19
+ def self.down
20
+ drop_table :wice_grid_serialized_queries
21
+ end
22
+ end
23
+
24
+ CreateWiceGridSerializedQueriesTable.up
25
+ end
26
+
27
+
28
+ end
@@ -0,0 +1,486 @@
1
+ # encoding: UTF-8
2
+ module Wice
3
+
4
+ class ViewColumn #:nodoc:
5
+ include ActionView::Helpers::FormTagHelper
6
+ include ActionView::Helpers::TagHelper
7
+ include ActionView::Helpers::JavaScriptHelper
8
+ include ActionView::Helpers::AssetTagHelper
9
+
10
+ # fields defined from the options parameter
11
+ FIELDS = [:attribute_name, :column_name, :td_html_attrs, :no_filter, :model_class, :allow_multiple_selection,
12
+ :in_html, :in_csv, :helper_style, :table_alias, :custom_order, :detach_with_id, :allow_ordering, :auto_reload]
13
+
14
+ attr_accessor *FIELDS
15
+
16
+ attr_accessor :cell_rendering_block, :grid, :css_class, :table_name, :main_table, :model_class, :custom_filter
17
+
18
+ attr_reader :contains_a_text_input
19
+
20
+ def initialize(block, options, grid_obj, tname, mtable, cfilter, view) #:nodoc:
21
+ self.cell_rendering_block = block
22
+ self.grid = grid_obj
23
+ self.table_name = tname
24
+ self.main_table = mtable
25
+ self.custom_filter = cfilter
26
+ @view = view
27
+
28
+ FIELDS.each do |field|
29
+ self.send(field.to_s + '=', options[field])
30
+ end
31
+ end
32
+
33
+ cattr_accessor :handled_type
34
+ @@handled_type = Hash.new
35
+
36
+ def css_class #:nodoc:
37
+ @css_class || ''
38
+ end
39
+
40
+ def yield_declaration_of_column_filter #:nodoc:
41
+ nil
42
+ end
43
+
44
+ def detachness #:nodoc:
45
+ (! detach_with_id.blank?).to_s
46
+ end
47
+
48
+ def yield_javascript #:nodoc:
49
+ declaration = yield_declaration_of_column_filter
50
+ if declaration
51
+ %!#{@grid.name}.register( {
52
+ filter_name : "#{self.column_name}",
53
+ detached : #{detachness},
54
+ #{declaration}
55
+ } ); !
56
+ else
57
+ ''
58
+ end
59
+ end
60
+
61
+
62
+ def config #:nodoc:
63
+ @view.config
64
+ end
65
+
66
+ def controller #:nodoc:
67
+ @view.controller
68
+ end
69
+
70
+
71
+ def render_filter #:nodoc:
72
+ params = @grid.filter_params(self)
73
+ res = render_filter_internal(params)
74
+ return (res.is_a?(Array)) ? res : [res, nil]
75
+ end
76
+
77
+ def render_filter_internal(params) #:nodoc:
78
+ '<!-- implement me! -->'
79
+ end
80
+
81
+ def form_parameter_name_id_and_query(v) #:nodoc:
82
+ query = form_parameter_template(v)
83
+ query_without_equals_sign = query.sub(/=$/,'')
84
+ parameter_name = CGI.unescape(query_without_equals_sign)
85
+ dom_id = id_out_of_name(parameter_name)
86
+ return query, query_without_equals_sign, parameter_name, dom_id.tr('.', '_')
87
+ end
88
+
89
+ # bad name, because for the main table the name is not really 'fully_qualified'
90
+ def attribute_name_fully_qualified_for_all_but_main_table_columns #:nodoc:
91
+ self.main_table ? attribute_name : table_alias_or_table_name + '.' + attribute_name
92
+ end
93
+
94
+ def fully_qualified_attribute_name #:nodoc:
95
+ table_alias_or_table_name + '.' + attribute_name
96
+ end
97
+
98
+
99
+ def filter_shown? #:nodoc:
100
+ self.attribute_name && ! self.no_filter
101
+ end
102
+
103
+ def filter_shown_in_main_table? #:nodoc:
104
+ filter_shown? && ! self.detach_with_id
105
+ end
106
+
107
+
108
+ def table_alias_or_table_name #:nodoc:
109
+ table_alias || table_name
110
+ end
111
+
112
+ def capable_of_hosting_filter_related_icons? #:nodoc:
113
+ self.attribute_name.blank? && self.column_name.blank? && ! self.filter_shown?
114
+ end
115
+
116
+ def has_auto_reloading_input? #:nodoc:
117
+ false
118
+ end
119
+
120
+ def auto_reloading_input_with_negation_checkbox? #:nodoc:
121
+ false
122
+ end
123
+
124
+ def has_auto_reloading_select? #:nodoc:
125
+ false
126
+ end
127
+
128
+ def has_auto_reloading_calendar? #:nodoc:
129
+ false
130
+ end
131
+
132
+ protected
133
+
134
+ def form_parameter_template(v) #:nodoc:
135
+ {@grid.name => {:f => {self.attribute_name_fully_qualified_for_all_but_main_table_columns => v}}}.to_query
136
+ end
137
+
138
+ def form_parameter_name(v) #:nodoc:
139
+ form_parameter_template_hash(v).to_query
140
+ end
141
+
142
+ def name_out_of_template(s) #:nodoc:
143
+ CGI.unescape(s).sub(/=$/,'')
144
+ end
145
+
146
+ def id_out_of_name(s) #:nodoc:
147
+ s.gsub(/[\[\]]+/,'_').sub(/_+$/, '')
148
+ end
149
+
150
+ end
151
+
152
+ class ActionViewColumn < ViewColumn #:nodoc:
153
+ def initialize(grid_obj, td_html_attrs, param_name, select_all_buttons, object_property, view) #:nodoc:
154
+ @view = view
155
+ @select_all_buttons = select_all_buttons
156
+ self.grid = grid_obj
157
+ self.td_html_attrs = td_html_attrs
158
+ self.td_html_attrs.add_or_append_class_value!('sel')
159
+ grid_name = self.grid.name
160
+ @param_name = param_name
161
+ @cell_rendering_block = lambda do |object, params|
162
+ selected = if params[grid_name] && params[grid_name][param_name] &&
163
+ params[grid_name][param_name].index(object.send(object_property).to_s)
164
+ true
165
+ else
166
+ false
167
+ end
168
+ check_box_tag("#{grid_name}[#{param_name}][]", object.send(object_property), selected, :id => nil)
169
+ end
170
+ end
171
+
172
+ def in_html #:nodoc:
173
+ true
174
+ end
175
+
176
+ def capable_of_hosting_filter_related_icons? #:nodoc:
177
+ false
178
+ end
179
+
180
+ def column_name #:nodoc:
181
+ return '' unless @select_all_buttons
182
+ select_all_tootip = WiceGridNlMessageProvider.get_message(:SELECT_ALL)
183
+ deselect_all_tootip = WiceGridNlMessageProvider.get_message(:DESELECT_ALL)
184
+
185
+ html = content_tag(:span, image_tag(Defaults::TICK_ALL_ICON, :alt => select_all_tootip),
186
+ :class => 'clickable select_all', :title => select_all_tootip) + ' ' +
187
+ content_tag(:span, image_tag(Defaults::UNTICK_ALL_ICON, :alt => deselect_all_tootip),
188
+ :class => 'clickable deselect_all', :title => deselect_all_tootip)
189
+
190
+ js = JsAdaptor.action_column_initialization(grid.name)
191
+
192
+ [html, js]
193
+ end
194
+
195
+ end
196
+
197
+ class ViewColumnInteger < ViewColumn #:nodoc:
198
+ @@handled_type[:integer] = self
199
+
200
+ def render_filter_internal(params) #:nodoc:
201
+ @contains_a_text_input = true
202
+
203
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(:fr => '')
204
+ @query2, _, parameter_name2, @dom_id2 = form_parameter_name_id_and_query(:to => '')
205
+
206
+ opts1 = {:size => 3, :id => @dom_id}
207
+ opts2 = {:size => 3, :id => @dom_id2}
208
+
209
+ if auto_reload
210
+ opts1[:class] = ' auto_reload'
211
+ opts2[:class] = ' auto_reload'
212
+ end
213
+
214
+ text_field_tag(parameter_name, params[:fr], opts1) + text_field_tag(parameter_name2, params[:to], opts2)
215
+ end
216
+
217
+ def yield_declaration_of_column_filter #:nodoc:
218
+ %$templates : ['#{@query}', '#{@query2}'],
219
+ ids : ['#{@dom_id}', '#{@dom_id2}'] $
220
+ end
221
+
222
+ def has_auto_reloading_input? #:nodoc:
223
+ auto_reload
224
+ end
225
+
226
+ end
227
+
228
+ class ViewColumnFloat < ViewColumnInteger #:nodoc:
229
+ @@handled_type[:decimal] = self
230
+ @@handled_type[:float] = self
231
+ end
232
+
233
+ class ViewColumnCustomDropdown < ViewColumn #:nodoc:
234
+ include ActionView::Helpers::FormOptionsHelper
235
+
236
+ attr_accessor :filter_all_label
237
+ attr_accessor :custom_filter
238
+
239
+ def render_filter_internal(params) #:nodoc:
240
+ @query, @query_without_equals_sign, @parameter_name, @dom_id = form_parameter_name_id_and_query('')
241
+ @query_without_equals_sign += '%5B%5D='
242
+
243
+ @custom_filter = @custom_filter.call if @custom_filter.kind_of? Proc
244
+
245
+ if @custom_filter.kind_of? Array
246
+
247
+ @custom_filter = [[@filter_all_label, nil]] + @custom_filter.map{|label, value|
248
+ [label.to_s, value.to_s]
249
+ }
250
+
251
+ end
252
+
253
+ select_options = {:name => @parameter_name, :id => @dom_id, :class => 'custom_dropdown'}
254
+
255
+ if @turn_off_select_toggling
256
+ select_toggle = ''
257
+ else
258
+ if self.allow_multiple_selection
259
+ select_options[:multiple] = params.is_a?(Array) && params.size > 1
260
+ select_toggle = content_tag(:a,
261
+ tag(:img, :alt => 'Expand/Collapse', :src => Defaults::TOGGLE_MULTI_SELECT_ICON),
262
+ :href => "javascript: toggle_multi_select('#{@dom_id}', this, 'Expand', 'Collapse');", # TO DO: to locales
263
+ :class => 'toggle_multi_select_icon', :title => 'Expand')
264
+ else
265
+ select_options[:multiple] = false
266
+ select_toggle = ''
267
+ end
268
+ end
269
+
270
+ if auto_reload
271
+ select_options[:class] += ' auto_reload'
272
+ end
273
+
274
+ params_for_select = (params.is_a?(Hash) && params.empty?) ? [nil] : params
275
+
276
+ '<span class="custom_dropdown_container">'.html_safe_if_necessary +
277
+ content_tag(:select,
278
+ options_for_select(@custom_filter, params_for_select),
279
+ select_options) +
280
+ select_toggle.html_safe_if_necessary + '</span>'.html_safe_if_necessary
281
+ end
282
+
283
+ def yield_declaration_of_column_filter #:nodoc:
284
+ %$templates : ['#{@query_without_equals_sign}'],
285
+ ids : ['#{@dom_id}'] $
286
+ end
287
+
288
+ def has_auto_reloading_select? #:nodoc:
289
+ auto_reload
290
+ end
291
+ end
292
+
293
+ class ViewColumnBoolean < ViewColumnCustomDropdown #:nodoc:
294
+ @@handled_type[:boolean] = self
295
+ include ActionView::Helpers::FormOptionsHelper
296
+
297
+ attr_accessor :boolean_filter_true_label, :boolean_filter_false_label
298
+
299
+ def render_filter_internal(params) #:nodoc:
300
+ @custom_filter = {
301
+ @filter_all_label => nil,
302
+ @boolean_filter_true_label => 't',
303
+ @boolean_filter_false_label => 'f'
304
+ }
305
+
306
+ @turn_off_select_toggling = true
307
+ super(params)
308
+ end
309
+ end
310
+
311
+ class ViewColumnDatetime < ViewColumn #:nodoc:
312
+ @@handled_type[:datetime] = self
313
+ @@handled_type[:timestamp] = self
314
+ include ActionView::Helpers::DateHelper
315
+ include Wice::JsCalendarHelpers
316
+
317
+
318
+ # name_and_id_from_options in Rails Date helper does not substitute '.' with '_'
319
+ # like all other simpler form helpers do. Thus, overriding it here.
320
+ def name_and_id_from_options(options, type) #:nodoc:
321
+ options[:name] = (options[:prefix] || DEFAULT_PREFIX) + (options[:discard_type] ? '' : "[#{type}]")
322
+ options[:id] = options[:name].gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '').gsub(/\./, '_').gsub(/_+/, '_')
323
+ end
324
+
325
+ @@datetime_chunk_names = %w(year month day hour minute)
326
+
327
+ def prepare_for_standard_filter #:nodoc:
328
+ x = lambda{|sym|
329
+ @@datetime_chunk_names.collect{|datetime_chunk_name|
330
+ triple = form_parameter_name_id_and_query(sym => {datetime_chunk_name => ''})
331
+ [triple[0], triple[3]]
332
+ }
333
+ }
334
+
335
+ @queris_ids = x.call(:fr) + x.call(:to)
336
+
337
+ _, _, @name1, _ = form_parameter_name_id_and_query({:fr => ''})
338
+ _, _, @name2, _ = form_parameter_name_id_and_query({:to => ''})
339
+ end
340
+
341
+
342
+ def prepare_for_calendar_filter #:nodoc:
343
+ query, _, @name1, @dom_id = form_parameter_name_id_and_query(:fr => '')
344
+ query2, _, @name2, @dom_id2 = form_parameter_name_id_and_query(:to => '')
345
+
346
+ @queris_ids = [[query, @dom_id], [query2, @dom_id2] ]
347
+ end
348
+
349
+
350
+ def render_standard_filter_internal(params) #:nodoc:
351
+ '<div class="date-filter">' +
352
+ select_datetime(params[:fr], {:include_blank => true, :prefix => @name1}) + '<br/>' +
353
+ select_datetime(params[:to], {:include_blank => true, :prefix => @name2}) +
354
+ '</div>'
355
+ end
356
+
357
+ def render_calendar_filter_internal(params) #:nodoc:
358
+ html1, js1 = datetime_calendar_prototype(params[:fr], @view,
359
+ {:include_blank => true, :prefix => @name1, :id => @dom_id, :fire_event => auto_reload},
360
+ :title => WiceGridNlMessageProvider.get_message(:DATE_SELECTOR_TOOLTIP_FROM))
361
+ html2, js2 = datetime_calendar_prototype(params[:to], @view,
362
+ {:include_blank => true, :prefix => @name2, :id => @dom_id2, :fire_event => auto_reload},
363
+ :title => WiceGridNlMessageProvider.get_message(:DATE_SELECTOR_TOOLTIP_TO))
364
+ [%!<div class="date-filter">#{html1}<br/>#{html2}</div>!, js1 + js2]
365
+ end
366
+
367
+
368
+ def render_filter_internal(params) #:nodoc:
369
+ # falling back to the Rails helpers for Datetime
370
+ if helper_style == :standard || Defaults::JS_FRAMEWORK == :jquery
371
+ prepare_for_standard_filter
372
+ render_standard_filter_internal(params)
373
+ else
374
+ prepare_for_calendar_filter
375
+ render_calendar_filter_internal(params)
376
+ end
377
+ end
378
+
379
+ def yield_declaration_of_column_filter #:nodoc:
380
+ %$templates : [ #{@queris_ids.collect{|tuple| "'" + tuple[0] + "'"}.join(', ')} ],
381
+ ids : [ #{@queris_ids.collect{|tuple| "'" + tuple[1] + "'"}.join(', ')} ] $
382
+ end
383
+
384
+ def has_auto_reloading_calendar? #:nodoc:
385
+ auto_reload && helper_style == :calendar
386
+ end
387
+
388
+ end
389
+
390
+ class ViewColumnDate < ViewColumnDatetime #:nodoc:
391
+ @@handled_type[:date] = self
392
+
393
+ @@datetime_chunk_names = %w(year month day)
394
+
395
+ def render_standard_filter_internal(params) #:nodoc:
396
+ '<div class="date-filter">' +
397
+ select_date(params[:fr], {:include_blank => true, :prefix => @name1, :id => @dom_id}) + '<br/>' +
398
+ select_date(params[:to], {:include_blank => true, :prefix => @name2, :id => @dom_id2}) +
399
+ '</div>'
400
+ end
401
+
402
+ def render_calendar_filter_internal(params) #:nodoc:
403
+
404
+ calendar_helper_method = if Wice::Defaults::JS_FRAMEWORK == :prototype
405
+ :date_calendar_prototype
406
+ else
407
+ :date_calendar_jquery
408
+ end
409
+
410
+ html1, js1 = send(calendar_helper_method, params[:fr], @view,
411
+ {:include_blank => true, :prefix => @name1, :fire_event => auto_reload},
412
+ :title => WiceGridNlMessageProvider.get_message(:DATE_SELECTOR_TOOLTIP_FROM))
413
+ html2, js2 = send(calendar_helper_method, params[:to], @view,
414
+ {:include_blank => true, :prefix => @name2, :fire_event => auto_reload},
415
+ :title => WiceGridNlMessageProvider.get_message(:DATE_SELECTOR_TOOLTIP_TO))
416
+
417
+ [%!<div class="date-filter">#{html1}<br/>#{html2}</div>!, js1 + js2]
418
+ end
419
+
420
+ def render_filter_internal(params) #:nodoc:
421
+
422
+ if helper_style == :standard
423
+ prepare_for_standard_filter
424
+ render_standard_filter_internal(params)
425
+ else
426
+ prepare_for_calendar_filter
427
+ render_calendar_filter_internal(params)
428
+ end
429
+ end
430
+ end
431
+
432
+ class ViewColumnString < ViewColumn #:nodoc:
433
+ @@handled_type[:string] = self
434
+ @@handled_type[:text] = self
435
+
436
+ attr_accessor :negation, :auto_reloading_input_with_negation_checkbox
437
+
438
+ def render_filter_internal(params) #:nodoc:
439
+ @contains_a_text_input = true
440
+ css_class = auto_reload ? 'auto_reload' : nil
441
+
442
+ if negation
443
+ self.auto_reloading_input_with_negation_checkbox = true if auto_reload
444
+
445
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(:v => '')
446
+ @query2, _, parameter_name2, @dom_id2 = form_parameter_name_id_and_query(:n => '')
447
+
448
+ '<div class="text_filter_container">' +
449
+ text_field_tag(parameter_name, params[:v], :size => 8, :id => @dom_id, :class => css_class) +
450
+ if defined?(::Wice::Defaults::NEGATION_CHECKBOX_LABEL) && ! ::Wice::Defaults::NEGATION_CHECKBOX_LABEL.blank?
451
+ ::Wice::Defaults::NEGATION_CHECKBOX_LABEL
452
+ else
453
+ ''
454
+ end +
455
+ check_box_tag(parameter_name2, '1', (params[:n] == '1'),
456
+ :id => @dom_id2,
457
+ :title => WiceGridNlMessageProvider.get_message(:NEGATION_CHECKBOX_TITLE),
458
+ :class => 'negation_checkbox') +
459
+ '</div>'
460
+ else
461
+ @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query('')
462
+ text_field_tag(parameter_name, (params.blank? ? '' : params), :size => 8, :id => @dom_id, :class => css_class)
463
+ end
464
+ end
465
+
466
+ def yield_declaration_of_column_filter #:nodoc:
467
+ if negation
468
+ %$templates : ['#{@query}', '#{@query2}'],
469
+ ids : ['#{@dom_id}', '#{@dom_id2}'] $
470
+ else
471
+ %$templates : ['#{@query}'],
472
+ ids : ['#{@dom_id}'] $
473
+ end
474
+ end
475
+
476
+ def has_auto_reloading_input? #:nodoc:
477
+ auto_reload
478
+ end
479
+
480
+ def auto_reloading_input_with_negation_checkbox? #:nodoc:
481
+ self.auto_reloading_input_with_negation_checkbox
482
+ end
483
+
484
+ end
485
+
486
+ end