mongoid_wice_grid 4.0.0
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.
- data/.gitignore +9 -0
- data/CHANGELOG +409 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +140 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +1188 -0
- data/Rakefile +40 -0
- data/SAVED_QUERIES_HOWTO.rdoc +123 -0
- data/VERSION +1 -0
- data/lib/filter_conditions_generators.rb +126 -0
- data/lib/generators/wice_grid/templates/calendarview.css +107 -0
- data/lib/generators/wice_grid/templates/calendarview.js +1168 -0
- data/lib/generators/wice_grid/templates/icons/arrow_down.gif +0 -0
- data/lib/generators/wice_grid/templates/icons/arrow_up.gif +0 -0
- data/lib/generators/wice_grid/templates/icons/calendar_view_month.png +0 -0
- data/lib/generators/wice_grid/templates/icons/delete.png +0 -0
- data/lib/generators/wice_grid/templates/icons/expand.png +0 -0
- data/lib/generators/wice_grid/templates/icons/page_white_excel.png +0 -0
- data/lib/generators/wice_grid/templates/icons/page_white_find.png +0 -0
- data/lib/generators/wice_grid/templates/icons/table.png +0 -0
- data/lib/generators/wice_grid/templates/icons/table_refresh.png +0 -0
- data/lib/generators/wice_grid/templates/icons/tick_all.png +0 -0
- data/lib/generators/wice_grid/templates/icons/untick_all.png +0 -0
- data/lib/generators/wice_grid/templates/wice_grid.css +173 -0
- data/lib/generators/wice_grid/templates/wice_grid.yml +269 -0
- data/lib/generators/wice_grid/templates/wice_grid_config.rb +215 -0
- data/lib/generators/wice_grid/templates/wice_grid_jquery.js +161 -0
- data/lib/generators/wice_grid/templates/wice_grid_prototype.js +153 -0
- data/lib/generators/wice_grid/wice_grid_assets_jquery_generator.rb +32 -0
- data/lib/generators/wice_grid/wice_grid_assets_prototype_generator.rb +34 -0
- data/lib/grid_output_buffer.rb +52 -0
- data/lib/grid_renderer.rb +547 -0
- data/lib/helpers/js_calendar_helpers.rb +183 -0
- data/lib/helpers/wice_grid_misc_view_helpers.rb +113 -0
- data/lib/helpers/wice_grid_serialized_queries_view_helpers.rb +82 -0
- data/lib/helpers/wice_grid_view_helpers.rb +761 -0
- data/lib/js_adaptors/jquery_adaptor.rb +145 -0
- data/lib/js_adaptors/js_adaptor.rb +12 -0
- data/lib/js_adaptors/prototype_adaptor.rb +168 -0
- data/lib/mongoid_field.rb +50 -0
- data/lib/tasks/wice_grid_tasks.rake +28 -0
- data/lib/view_columns.rb +464 -0
- data/lib/views/create.rjs +13 -0
- data/lib/views/delete.rjs +12 -0
- data/lib/wice_grid.rb +521 -0
- data/lib/wice_grid_controller.rb +165 -0
- data/lib/wice_grid_core_ext.rb +179 -0
- data/lib/wice_grid_misc.rb +99 -0
- data/lib/wice_grid_serialized_queries_controller.rb +77 -0
- data/lib/wice_grid_serialized_query.rb +14 -0
- data/lib/wice_grid_spreadsheet.rb +33 -0
- data/test/.gitignore +2 -0
- data/test/blueprint.rb +17 -0
- data/test/database.yml +21 -0
- data/test/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/test/public/javascripts/wice_grid.js +163 -0
- data/test/rails_mongoid_test.rb +104 -0
- data/test/rails_test_app.rb +71 -0
- data/test/require_gems.rb +19 -0
- data/test/schema.rb +33 -0
- data/test/spec_helper.rb +22 -0
- data/test/test_helper.rb +89 -0
- data/test/views/projects_and_people_grid.html.erb +12 -0
- data/test/views/projects_and_people_grid_invalid.html.erb +12 -0
- data/test/views/simple_projects_grid.html.erb +9 -0
- data/test/wice_grid_core_ext_test.rb +183 -0
- data/test/wice_grid_functional_test.rb +68 -0
- data/test/wice_grid_initializer.rb +215 -0
- data/test/wice_grid_misc_test.rb +41 -0
- data/test/wice_grid_test.rb +42 -0
- data/test/wice_grid_view_helper_test.rb +12 -0
- metadata +150 -0
@@ -0,0 +1,183 @@
|
|
1
|
+
module Wice
|
2
|
+
module JsCalendarHelpers
|
3
|
+
|
4
|
+
# Jquery
|
5
|
+
|
6
|
+
def date_calendar_jquery(initial_date, view, opts = {}, html_opts = {}) #:nodoc:
|
7
|
+
date_format = Wice::Defaults::DATE_FORMAT
|
8
|
+
|
9
|
+
options, name, date_string, dom_id, datepicker_placeholder_id, date_span_id =
|
10
|
+
prepare_data_for_calendar(opts, date_format, initial_date)
|
11
|
+
|
12
|
+
remove_date_function = %! $('##{date_span_id}').html(''); $('##{dom_id}')[0].value = ''; !
|
13
|
+
|
14
|
+
date_picker =
|
15
|
+
|
16
|
+
hidden_field_tag(name, date_string, :id => dom_id) + ' ' +
|
17
|
+
|
18
|
+
link_to_function(
|
19
|
+
content_tag(:span, date_string, :id => date_span_id),
|
20
|
+
remove_date_function,
|
21
|
+
:class => 'date_label',
|
22
|
+
:title => ::Wice::WiceGridNlMessageProvider.get_message(:DATE_STRING_TOOLTIP))
|
23
|
+
|
24
|
+
html = "<span id=\"#{datepicker_placeholder_id}\">#{date_picker}</span>"
|
25
|
+
|
26
|
+
javascript = calendar_constructor_jquery(dom_id, view, Wice::Defaults::DATE_FORMAT_JQUERY,
|
27
|
+
date_span_id, opts[:fire_event], html_opts[:title], datepicker_placeholder_id)
|
28
|
+
|
29
|
+
[html, javascript]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Prototype
|
33
|
+
def date_calendar_prototype(initial_date, view, opts = {}, html_opts = {}) #:nodoc:
|
34
|
+
select_date_datetime_common_prototype(initial_date, view, opts, html_opts, false, Wice::Defaults::DATE_FORMAT)
|
35
|
+
end
|
36
|
+
|
37
|
+
def datetime_calendar_prototype(initial_date, view, opts = {}, html_opts = {}) #:nodoc:
|
38
|
+
select_date_datetime_common_prototype(initial_date, view, opts, html_opts, true, Wice::Defaults::DATETIME_FORMAT)
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
# common
|
44
|
+
|
45
|
+
def prepare_data_for_calendar(opts, date_format, initial_date) #:nodoc:
|
46
|
+
options = {:prefix => 'date'}
|
47
|
+
options.merge!(opts)
|
48
|
+
name = options[:prefix]
|
49
|
+
date_string = initial_date.nil? ? '' : initial_date.strftime(date_format)
|
50
|
+
dom_id = options[:id] || name.gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '').gsub(/\./, '_').gsub(/_+/, '_')
|
51
|
+
datepicker_placeholder_id = dom_id + '_date_placeholder'
|
52
|
+
date_span_id = dom_id + '_date_view'
|
53
|
+
|
54
|
+
return options, name, date_string, dom_id, datepicker_placeholder_id, date_span_id
|
55
|
+
end
|
56
|
+
|
57
|
+
# jquery
|
58
|
+
|
59
|
+
def calendar_constructor_jquery(dom_id, view, date_format, date_span_id, fireEvent, title, datepicker_placeholder_id)
|
60
|
+
|
61
|
+
javascript = %| $( "##{dom_id}" ).datepicker({\n|
|
62
|
+
javascript << %| firstDay: 1,\n|
|
63
|
+
javascript << %| showOn: "button",\n|
|
64
|
+
javascript << %| dateFormat: "#{date_format}",\n|
|
65
|
+
javascript << %| buttonImage: "#{::Wice::Defaults::CALENDAR_ICON}",\n|
|
66
|
+
javascript << %| buttonImageOnly: true,\n|
|
67
|
+
javascript << %| buttonText: "#{title}",\n|
|
68
|
+
javascript << %| changeMonth: true,\n|
|
69
|
+
javascript << %| changeYear: true,\n|
|
70
|
+
javascript << %| onSelect: function(dateText, inst) {\n|
|
71
|
+
javascript << %| $("##{date_span_id}").html(dateText);\n|
|
72
|
+
if fireEvent
|
73
|
+
javascript << %| $("##{dom_id}").trigger('wg:calendarChanged');\n|
|
74
|
+
end
|
75
|
+
javascript << %| }\n|
|
76
|
+
javascript << %| });\n|
|
77
|
+
|
78
|
+
lang = Object.const_defined?(:I18n) ? I18n.locale : nil
|
79
|
+
|
80
|
+
if Rails.env == 'development'
|
81
|
+
unless view.respond_to? :datepicker_check_done
|
82
|
+
|
83
|
+
javascript << %| if (! $.datepicker ){\n|
|
84
|
+
javascript << %| alert("Seems like you do not have jQuery datepicker (http://jqueryui.com/demos/datepicker/)|
|
85
|
+
javascript << %| installed. Either install it or set Wice::Defaults::HELPER_STYLE to :standard in |
|
86
|
+
javascript << %| wice_grid_config.rb in order to use standard Rails date helpers")\n|
|
87
|
+
javascript << %| }\n|
|
88
|
+
|
89
|
+
def view.datepicker_check_done
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if lang
|
95
|
+
unless view.respond_to? :wg_calendar_lang_set
|
96
|
+
|
97
|
+
javascript << %| wgCalendarLangRegionalOptions = $.datepicker.regional['#{lang}'];\n|
|
98
|
+
javascript << %| if (wgCalendarLangRegionalOptions){\n|
|
99
|
+
javascript << %| delete wgCalendarLangRegionalOptions.dateFormat ;\n|
|
100
|
+
javascript << %| delete wgCalendarLangRegionalOptions.firstDate ;\n|
|
101
|
+
javascript << %| }\n|
|
102
|
+
|
103
|
+
def view.wg_calendar_lang_set
|
104
|
+
end
|
105
|
+
end
|
106
|
+
javascript << %| if (wgCalendarLangRegionalOptions){\n|
|
107
|
+
javascript << %| $( "##{dom_id}" ).datepicker("option", wgCalendarLangRegionalOptions);\n|
|
108
|
+
javascript << %| }\n|
|
109
|
+
end
|
110
|
+
|
111
|
+
javascript += %| $('##{datepicker_placeholder_id} .ui-datepicker-trigger').addClass('clickable');\n|
|
112
|
+
|
113
|
+
javascript
|
114
|
+
end
|
115
|
+
|
116
|
+
# prortotype
|
117
|
+
|
118
|
+
def calendar_constructor_prototype(popup_trigger_icon_id, view, dom_id, date_format,
|
119
|
+
date_span_id, with_time, fireEvent)
|
120
|
+
javascript = ''
|
121
|
+
|
122
|
+
unless view.respond_to? :wg_calendar_lang_set
|
123
|
+
lang = Object.const_defined?(:I18n) ? I18n.locale : nil
|
124
|
+
javascript << %| Calendar.language = '#{lang}';\n| unless lang.blank?
|
125
|
+
|
126
|
+
def view.wg_calendar_lang_set
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
javascript << %| new Calendar({\n |
|
132
|
+
javascript << %| popupTriggerElement : "#{popup_trigger_icon_id}",\n |
|
133
|
+
javascript << %| initialDate : $('#{dom_id}').value,\n |
|
134
|
+
if fireEvent
|
135
|
+
javascript << %| onHideCallback : function(){Event.fire($(#{dom_id}), 'wg:calendarChanged')},\n |
|
136
|
+
end
|
137
|
+
javascript << %| dateFormat : "#{date_format}",\n|
|
138
|
+
unless Wice::Defaults::POPUP_PLACEMENT_STRATEGY == :trigger
|
139
|
+
javascript << %| popupPositioningStrategy : "#{Wice::Defaults::POPUP_PLACEMENT_STRATEGY}",\n|
|
140
|
+
end
|
141
|
+
if with_time
|
142
|
+
javascript << %| withTime : true,\n|
|
143
|
+
end
|
144
|
+
javascript << %| outputFields : $A(['#{date_span_id}', '#{dom_id}'])\n |
|
145
|
+
javascript << %| });\n|
|
146
|
+
|
147
|
+
javascript
|
148
|
+
end
|
149
|
+
|
150
|
+
def select_date_datetime_common_prototype(initial_date, view, opts, html_opts, with_time, date_format) #:nodoc:
|
151
|
+
|
152
|
+
options, name, date_string, dom_id, datepicker_placeholder_id, date_span_id =
|
153
|
+
prepare_data_for_calendar(opts, date_format, initial_date)
|
154
|
+
|
155
|
+
popup_trigger_icon_id = dom_id + '_trigger'
|
156
|
+
|
157
|
+
function = %! $('#{date_span_id}').innerHTML = ''; $('#{dom_id}').value = ''; !
|
158
|
+
if opts[:fire_event]
|
159
|
+
function += "Event.fire($(#{dom_id}), 'wg:calendarChanged')"
|
160
|
+
end
|
161
|
+
|
162
|
+
date_picker = image_tag(Defaults::CALENDAR_ICON,
|
163
|
+
:id => popup_trigger_icon_id,
|
164
|
+
:class => 'clickable',
|
165
|
+
:title => html_opts[:title]) +
|
166
|
+
|
167
|
+
link_to_function(
|
168
|
+
content_tag(:span, date_string, :id => date_span_id),
|
169
|
+
function,
|
170
|
+
:class => 'date_label',
|
171
|
+
:title => WiceGridNlMessageProvider.get_message(:DATE_STRING_TOOLTIP)) + ' ' +
|
172
|
+
|
173
|
+
hidden_field_tag(name, date_string, :class => 'text-input', :id => dom_id)
|
174
|
+
|
175
|
+
html = "<span id=\"#{datepicker_placeholder_id}\">#{date_picker}</span>"
|
176
|
+
|
177
|
+
javascript = calendar_constructor_prototype(popup_trigger_icon_id, view, dom_id, date_format, date_span_id, with_time, opts[:fire_event])
|
178
|
+
|
179
|
+
[html, javascript]
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Wice
|
3
|
+
module GridViewHelper
|
4
|
+
|
5
|
+
|
6
|
+
# This method dumps all HTTP parameters related to filtering and ordering of a certain grid as hidden form fields.
|
7
|
+
# This might be required if you want to keep the state of a grid while reloading the page using other forms.
|
8
|
+
#
|
9
|
+
# The only parameter is a grid object returned by +initialize_grid+ in the controller.
|
10
|
+
def dump_filter_parameters_as_hidden_fields(grid)
|
11
|
+
unless grid.kind_of? WiceGrid
|
12
|
+
raise WiceGridArgumentError.new("dump_filter_parameters_as_hidden_fields: the parameter must be a WiceGrid instance.")
|
13
|
+
end
|
14
|
+
|
15
|
+
grid.get_state_as_parameter_value_pairs(true).collect{|param_name, value|
|
16
|
+
hidden_field_tag(param_name, value)
|
17
|
+
}.join("\n").html_safe_if_necessary
|
18
|
+
end
|
19
|
+
|
20
|
+
def dump_state(grid) #:nodoc:
|
21
|
+
debug(grid.get_state_as_parameter_value_pairs)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# secret but stupid weapon - takes an ActiveRecord and using reflection tries to build all the column clauses by itself.
|
26
|
+
# WiceGrid is not a scaffolding solution, I hate scaffolding and how certain idiots associate scaffolding with Rails,
|
27
|
+
# so I do not document this method to avoid contributing to this misunderstanding.
|
28
|
+
def scaffolded_grid(grid_obj, opts = {}) #:nodoc:
|
29
|
+
unless grid_obj.kind_of? WiceGrid
|
30
|
+
raise WiceGridArgumentError.new("scaffolded_grid: the parameter must be a WiceGrid instance.")
|
31
|
+
end
|
32
|
+
|
33
|
+
# debug grid.klass.column_names
|
34
|
+
columns = grid_obj.klass.column_names
|
35
|
+
if opts[:reject_attributes].is_a? Proc
|
36
|
+
columns = columns.reject{|c| opts[:reject_attributes].call(c)}
|
37
|
+
opts.delete(:reject_attributes)
|
38
|
+
elsif
|
39
|
+
columns = columns.reject{|c| c =~ opts[:reject_attributes]}
|
40
|
+
opts.delete(:reject_attributes)
|
41
|
+
end
|
42
|
+
grid(grid_obj, opts) do |g|
|
43
|
+
columns.each do |column_name|
|
44
|
+
g.column :column_name => column_name.humanize, :attribute_name => column_name do |ar|
|
45
|
+
ar.send(column_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# View helper to include all stylesheets and javascript files needed for WiceGrid to function. Add it to template/layout in the
|
52
|
+
# page header section.
|
53
|
+
#
|
54
|
+
# By default the helper returns WiceGrid javascripts and stylesheets include statements only on demand, that is, only if at least one initialize_grid has been
|
55
|
+
# called in the controller. Otherwise the helper returns an empty string. However, you can force the old unconditioned behavior if you need by submitting
|
56
|
+
# parameter <tt>:load_on_demand</tt> set to +false+:
|
57
|
+
# <%= include_wice_grid_assets(:load_on_demand => false) %>
|
58
|
+
#
|
59
|
+
# By default +include_wice_grid_assets+ adds include statements for the javascript calendar widget used for date/datetime filters,
|
60
|
+
# but it's possible not to include them setting parameter +include_calendar+ to false:
|
61
|
+
# <%= include_wice_grid_assets(:include_calendar => false) %>
|
62
|
+
def include_wice_grid_assets(options = {})
|
63
|
+
opts = {:include_calendar => true, :load_on_demand => true}
|
64
|
+
options.assert_valid_keys(opts.keys)
|
65
|
+
opts.merge!(options)
|
66
|
+
|
67
|
+
if @__wice_grid_on_page || ! opts[:load_on_demand]
|
68
|
+
javascript_include_tag('wice_grid') +
|
69
|
+
stylesheet_link_tag('wice_grid') +
|
70
|
+
if opts[:include_calendar]
|
71
|
+
JsAdaptor.js_framework_specific_calendar_assets(self)
|
72
|
+
else
|
73
|
+
''
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a list of names of javascript files for WiceGrid thus providing compatibility with Rails asset caching.
|
79
|
+
# Mind the parameters, and the fact that Prototype has to be loaded before WiceGrid javascripts:
|
80
|
+
#
|
81
|
+
# <%= javascript_include_tag *([:defaults] + names_of_wice_grid_javascripts + [ 'ui', 'swfobject', {:cache => true}]) %>
|
82
|
+
#
|
83
|
+
# By default +names_of_wice_grid_javascripts+ returns all javascripts, but it's possible not to include calendar widget javascripts by
|
84
|
+
# setting parameter <tt>:include_calendar</tt> to +false+.
|
85
|
+
def names_of_wice_grid_javascripts(options = {})
|
86
|
+
opts = {:include_calendar => true}
|
87
|
+
options.assert_valid_keys(opts.keys)
|
88
|
+
opts.merge!(options)
|
89
|
+
res = ['wice_grid']
|
90
|
+
n = js_framework_specific_calendar_js_name
|
91
|
+
res << n if n && opts[:include_calendar]
|
92
|
+
res
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns a list of names of stylesheet files for WiceGrid thus providing compatibility with Rails asset caching.
|
96
|
+
# Mind the parameters, for example:
|
97
|
+
#
|
98
|
+
# <%= stylesheet_link_tag *(['core', 'modalbox'] + names_of_wice_grid_stylesheets + [ {:cache => true}]) %>
|
99
|
+
#
|
100
|
+
# By default +names_of_wice_grid_stylesheets+ returns all javascripts, but it's possible not to include calendar widget javascripts by
|
101
|
+
# setting parameter <tt>:include_calendar</tt> to +false+.
|
102
|
+
def names_of_wice_grid_stylesheets(options = {})
|
103
|
+
opts = {:include_calendar => true}
|
104
|
+
options.assert_valid_keys(opts.keys)
|
105
|
+
opts.merge!(options)
|
106
|
+
res = ['wice_grid']
|
107
|
+
n = js_framework_specific_calendar_css_name
|
108
|
+
res << n if n && opts[:include_calendar]
|
109
|
+
res
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Wice
|
3
|
+
module GridViewHelper
|
4
|
+
|
5
|
+
# View helper to render the list of saved queries and the form to create a new query.
|
6
|
+
# Parameters:
|
7
|
+
# * <tt>:extra_parameters</tt> - a hash of additional parameters to use when creating a new query object.
|
8
|
+
# Read section "Adding Application Specific Logic to Saving/Restoring Queries" in README for more details.
|
9
|
+
def saved_queries_panel(grid, opts = {})
|
10
|
+
unless grid.kind_of? WiceGrid
|
11
|
+
raise WiceGridArgumentError.new("saved_queries_panel: the parameter must be a WiceGrid instance.")
|
12
|
+
end
|
13
|
+
|
14
|
+
options = {:extra_parameters => {}}
|
15
|
+
opts.assert_valid_keys(options.keys)
|
16
|
+
options.merge!(opts)
|
17
|
+
|
18
|
+
grid_name = grid.name
|
19
|
+
id_and_name = "#{grid_name}_saved_query_name"
|
20
|
+
base_path_to_query_controller = create_serialized_query_url(:grid_name => grid_name)
|
21
|
+
|
22
|
+
parameters = grid.get_state_as_parameter_value_pairs
|
23
|
+
|
24
|
+
options[:extra_parameters].each do |k, v|
|
25
|
+
parameters << [ CGI.unescape({:extra => {k => ''}}.to_query.sub(/=$/,'')) , v.to_s ]
|
26
|
+
end
|
27
|
+
parameters << ['authenticity_token', form_authenticity_token]
|
28
|
+
|
29
|
+
(%! <div class="wice_grid_query_panel"><h3>#{WiceGridNlMessageProvider.get_message(:SAVED_QUERY_PANEL_TITLE)}</h3>! +
|
30
|
+
saved_queries_list(grid_name, grid.saved_query, options[:extra_parameters]) +
|
31
|
+
%!<div id="#{grid_name}_notification_messages" onmouseover="#{Wice::JsAdaptor.fade_this}"></div>! +
|
32
|
+
if block_given?
|
33
|
+
view, ids = yield
|
34
|
+
view
|
35
|
+
else
|
36
|
+
''
|
37
|
+
end +
|
38
|
+
text_field_tag(id_and_name, '', :size => 20, :onkeydown=>'', :id => id_and_name) +
|
39
|
+
button_to_function(WiceGridNlMessageProvider.get_message(:SAVE_QUERY_BUTTON_LABEL), "#{grid_name}_save_query()" ) +
|
40
|
+
'</div>' +
|
41
|
+
javascript_tag do
|
42
|
+
JsAdaptor.call_to_save_query_and_key_event_initialization_for_saving_queries(
|
43
|
+
id_and_name, grid_name, base_path_to_query_controller, parameters.to_json, ids.to_json
|
44
|
+
)
|
45
|
+
end
|
46
|
+
).html_safe
|
47
|
+
end
|
48
|
+
|
49
|
+
def saved_queries_list(grid_name, saved_query = nil, extra_parameters = nil) #:nodoc:
|
50
|
+
|
51
|
+
link_title = WiceGridNlMessageProvider.get_message(:SAVED_QUERY_LINK_TITLE)
|
52
|
+
deletion_confirmation = WiceGridNlMessageProvider.get_message(:SAVED_QUERY_DELETION_CONFIRMATION)
|
53
|
+
deletion_link_title = WiceGridNlMessageProvider.get_message(:SAVED_QUERY_DELETION_LINK_TITLE)
|
54
|
+
|
55
|
+
query_store_model = ::Wice::get_query_store_model
|
56
|
+
currently_loaded_query_id = saved_query ? saved_query.id : nil
|
57
|
+
with = extra_parameters.nil? ? nil : "'" + {:extra => extra_parameters}.to_query + "'"
|
58
|
+
|
59
|
+
%!<ul id="#{grid_name}_query_list" class="query_list"> ! +
|
60
|
+
query_store_model.list(grid_name, controller).collect do |sq|
|
61
|
+
link_opts = {:class => 'query_load_link', :title => "#{link_title} #{sq.name}"}
|
62
|
+
link_opts[:class] += ' current' if saved_query == sq
|
63
|
+
"<li>"+
|
64
|
+
link_to_remote(image_tag(Defaults::DELETE_QUERY_ICON),
|
65
|
+
{:url => delete_serialized_query_path(:grid_name => grid_name, :id => sq.id, :current => currently_loaded_query_id ),
|
66
|
+
:confirm => deletion_confirmation, :with => with},
|
67
|
+
{:title => "#{deletion_link_title} #{sq.name}"} ) + ' ' +
|
68
|
+
link_to_function(h(sq.name),
|
69
|
+
%/ if (typeof(#{grid_name}) != "undefined") #{grid_name}.load_query(#{sq.id}) /,
|
70
|
+
link_opts) +
|
71
|
+
if sq.respond_to? :description
|
72
|
+
desc = sq.description
|
73
|
+
desc.blank? ? '' : " <i>#{desc}</i>"
|
74
|
+
else
|
75
|
+
''
|
76
|
+
end +
|
77
|
+
'</li>'
|
78
|
+
end.join('') + '</ul>'
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,761 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Wice
|
3
|
+
module GridViewHelper
|
4
|
+
|
5
|
+
# View helper for rendering the grid.
|
6
|
+
#
|
7
|
+
# The first parameter is a grid object returned by +initialize_grid+ in the controller.
|
8
|
+
#
|
9
|
+
# The second parameter is a hash of options:
|
10
|
+
# * <tt>:table_html_attrs</tt> - a hash of HTML attributes to be included into the <tt>table</tt> tag.
|
11
|
+
# * <tt>:class</tt> - a shortcut for <tt>:table_html_attrs => {:class => 'css_class'}</tt>
|
12
|
+
# * <tt>:header_tr_html_attrs</tt> - a hash of HTML attributes to be included into the first <tt>tr</tt> tag
|
13
|
+
# (or two first <tt>tr</tt>'s if the filter row is present).
|
14
|
+
# * <tt>:show_filters</tt> - defines when the filter is shown. Possible values are:
|
15
|
+
# * <tt>:when_filtered</tt> - the filter is shown when the current table is the result of filtering
|
16
|
+
# * <tt>:always</tt> or <tt>true</tt> - show the filter always
|
17
|
+
# * <tt>:no</tt> or <tt>false</tt> - never show the filter
|
18
|
+
# * <tt>:upper_pagination_panel</tt> - a boolean value which defines whether there is an additional pagination
|
19
|
+
# panel on top of the table. By default it is false.
|
20
|
+
# * <tt>:extra_request_parameters</tt> - a hash which will be added as additional HTTP request parameters to all
|
21
|
+
# links generated by the grid, be it sorting links, filters, or the 'Reset Filter' icon.
|
22
|
+
# Please note that WiceGrid respects and retains all request parameters already present in the URL which
|
23
|
+
# formed the page, so there is no need to enumerate them in <tt>:extra_request_parameters</tt>. A typical
|
24
|
+
# usage of <tt>:extra_request_parameters</tt> is a page with javascript tabs - changing the active tab
|
25
|
+
# does not reload the page, but if one such tab contains a WiceGrid, it could be required that if the user
|
26
|
+
# orders or filters the grid, the result page should have the tab with the grid activated. For this we
|
27
|
+
# need to send an additional parameter specifying from which tab the request was generated.
|
28
|
+
# * <tt>:sorting_dependant_row_cycling</tt> - When set to true (by default it is false) the row styles +odd+
|
29
|
+
# and +even+ will be changed only when the content of the cell belonging to the sorted column changes.
|
30
|
+
# In other words, rows with identical values in the ordered column will have the same style (color).
|
31
|
+
# * <tt>:erb_mode</tt> - can be <tt>true</tt> or <tt>false</tt>. Defines the style of the helper method
|
32
|
+
# in the view. The default is <tt>false</tt>.
|
33
|
+
# * <tt>:allow_showing_all_records</tt> - allow or prohibit the "All Records" mode.
|
34
|
+
# * <tt>:hide_reset_button</tt> - Do not show the default Filter Reset button.
|
35
|
+
# Useful when using a custom reset button (helper +reset_grid_javascript+).
|
36
|
+
# By default it is false.
|
37
|
+
# * <tt>:hide_submit_button</tt> - Do not show the default Filter Submit button.
|
38
|
+
# Useful when using a custom submit button (helper +submit_grid_javascript+).
|
39
|
+
# By default it is false.
|
40
|
+
# * <tt>:hide_csv_button</tt> - a boolean value which defines whether the default Export To CSV button
|
41
|
+
# should be rendered. Useful when using a custom Export To CSV button (helper +export_to_csv_javascript+).
|
42
|
+
# By default it is false.
|
43
|
+
# Please read README for more insights.
|
44
|
+
#
|
45
|
+
# The block contains definitions of grid columns using the +column+ method sent to the object yielded into
|
46
|
+
# the block. In other words, the value returned by each of the blocks defines the content of a cell, the
|
47
|
+
# first block is called for cells of the first column for each row (each ActiveRecord instance), the
|
48
|
+
# second block is called for cells of the second column, and so on. See the example:
|
49
|
+
#
|
50
|
+
# <%= grid(@accounts_grid, :table_html_attrs => {:class => 'grid_style', :id => 'accounts_grid'}, :header_tr_html_attrs => {:class => 'grid_headers'}) do |g|
|
51
|
+
#
|
52
|
+
# g.column :column_name => 'Username', :attribute_name => 'username' do |account|
|
53
|
+
# account.username
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# g.column :column_name => 'application_account.field.identity_id'._, :attribute_name => 'firstname', :model_class => Person do |account|
|
57
|
+
# link_to(account.identity.name, identity_path(account.identity))
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# g.column do |account|
|
61
|
+
# link_to('Edit', edit_account_path(account))
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# end -%>
|
65
|
+
#
|
66
|
+
# The helper may have two styles defined by the +erb_mode+ parameter to the +initialize_grid+ in the contoller.
|
67
|
+
# By default (<tt>erb_mode = false</tt>) this is a simple helper surrounded by <tt><%=</tt> and <tt>%></tt>:
|
68
|
+
#
|
69
|
+
# <%= grid(@countries_grid) do |g|
|
70
|
+
#
|
71
|
+
# g.column :column_name => 'Name', :attribute_name => 'name' do |country|
|
72
|
+
# link_to(country.name, country_path(country))
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# g.column :column_name => 'Numeric Code', :attribute_name => 'numeric_code' do |country|
|
76
|
+
# country.numeric_code
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# end -%>
|
80
|
+
#
|
81
|
+
#
|
82
|
+
#
|
83
|
+
# The second style (<tt>erb_mode = true</tt>) is called <em>ERB mode</em> and it allows to embed any ERB content inside blocks,
|
84
|
+
# which is basically the style of the
|
85
|
+
# <tt>form_for</tt> helper, only <tt>form_for</tt> takes one block, while inside the <tt>grid</tt> block there are other method calls taking
|
86
|
+
# blocks as parameters:
|
87
|
+
#
|
88
|
+
# <% grid(@countries_grid) do |g|
|
89
|
+
#
|
90
|
+
# <% g.column :column_name => 'Name', :attribute_name => 'name' do |country| %>
|
91
|
+
# <b>Name: <%= link_to(country.name, country_path(country)) %></b>
|
92
|
+
# <% end %>
|
93
|
+
#
|
94
|
+
# <% g.column :column_name => 'Numeric Code', :attribute_name => 'numeric_code' do |country| %>
|
95
|
+
# <i>Numeric Code: <%= country.numeric_code %></i>
|
96
|
+
# <% end %>
|
97
|
+
#
|
98
|
+
# <% end -%>
|
99
|
+
#
|
100
|
+
# This mode can be usable if you like to have much HTML code inside cells.
|
101
|
+
#
|
102
|
+
# Please remember that in this mode the helper opens with <tt><%</tt> instead of <tt><%=</tt>, similar to <tt>form_for</tt>.
|
103
|
+
#
|
104
|
+
# Defaults for parameters <tt>:show_filters</tt> and <tt>:upper_pagination_panel</tt>
|
105
|
+
# can be changed in <tt>lib/wice_grid_config.rb</tt> using constants <tt>Wice::Defaults::SHOW_FILTER</tt> and
|
106
|
+
# <tt>WiceGrid::Defaults::SHOW_UPPER_PAGINATION_PANEL</tt>, this is convenient if you want to set a project wide setting
|
107
|
+
# without having to repeat it for every grid instance.
|
108
|
+
#
|
109
|
+
# Pease read documentation about the +column+ method to achieve the enlightenment.
|
110
|
+
|
111
|
+
def grid(grid, opts = {}, &block)
|
112
|
+
unless grid.class == WiceGrid
|
113
|
+
raise WiceGridArgumentError.new("The first argument for the grid helper must be an instance of the WiceGrid class")
|
114
|
+
end
|
115
|
+
|
116
|
+
if grid.output_buffer
|
117
|
+
if grid.output_buffer == true
|
118
|
+
raise WiceGridException.new("Second occurence of grid helper with the same grid object. " +
|
119
|
+
"Did you intend to use detached filters and forget to define them?")
|
120
|
+
else
|
121
|
+
return grid.output_buffer
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
options = {
|
126
|
+
:allow_showing_all_records => Defaults::ALLOW_SHOWING_ALL_QUERIES,
|
127
|
+
:class => nil,
|
128
|
+
:erb_mode => Defaults::ERB_MODE,
|
129
|
+
:extra_request_parameters => {},
|
130
|
+
:header_tr_html_attrs => {},
|
131
|
+
:hide_reset_button => false,
|
132
|
+
:hide_submit_button => false,
|
133
|
+
:hide_csv_button => false,
|
134
|
+
:show_filters => Defaults::SHOW_FILTER,
|
135
|
+
:sorting_dependant_row_cycling => false,
|
136
|
+
:table_html_attrs => {},
|
137
|
+
:upper_pagination_panel => Defaults::SHOW_UPPER_PAGINATION_PANEL
|
138
|
+
}
|
139
|
+
|
140
|
+
opts.assert_valid_keys(options.keys)
|
141
|
+
|
142
|
+
options.merge!(opts)
|
143
|
+
|
144
|
+
options[:show_filters] = :no if options[:show_filters] == false
|
145
|
+
options[:show_filters] = :always if options[:show_filters] == true
|
146
|
+
|
147
|
+
options[:table_html_attrs].add_or_append_class_value!('wice_grid', true)
|
148
|
+
|
149
|
+
if options[:class]
|
150
|
+
options[:table_html_attrs].add_or_append_class_value!(options[:class])
|
151
|
+
options.delete(:class)
|
152
|
+
end
|
153
|
+
|
154
|
+
rendering = GridRenderer.new(grid, self)
|
155
|
+
rendering.erb_mode = options[:erb_mode]
|
156
|
+
|
157
|
+
block.call(rendering) # calling block containing column() calls
|
158
|
+
|
159
|
+
reuse_last_column_for_filter_buttons =
|
160
|
+
Defaults::REUSE_LAST_COLUMN_FOR_FILTER_ICONS && rendering.last_column_for_html.capable_of_hosting_filter_related_icons?
|
161
|
+
|
162
|
+
if grid.output_csv?
|
163
|
+
content = grid_csv(grid, rendering)
|
164
|
+
else
|
165
|
+
# If blank_slate is defined we don't show any grid at all
|
166
|
+
if rendering.blank_slate_handler && grid.resultset.size == 0 && ! grid.filtering_on?
|
167
|
+
content = generate_blank_slate(grid, rendering)
|
168
|
+
return prepare_result(rendering, grid, content, block)
|
169
|
+
end
|
170
|
+
|
171
|
+
content = grid_html(grid, options, rendering, reuse_last_column_for_filter_buttons)
|
172
|
+
end
|
173
|
+
|
174
|
+
grid.view_helper_finished = true
|
175
|
+
prepare_result(rendering, grid, content, block)
|
176
|
+
end
|
177
|
+
|
178
|
+
def prepare_result(rendering, grid, content, block) #:nodoc:
|
179
|
+
if rendering.erb_mode
|
180
|
+
# true in this case is a sign that grid_html has run in a normal mode, i.e. without detached filters
|
181
|
+
if grid.output_buffer.nil? || grid.output_buffer == true
|
182
|
+
content = content.to_s
|
183
|
+
if Rails.respond_to?(:version) && Rails.version.to_f >= 2.2
|
184
|
+
return concat(content)
|
185
|
+
else
|
186
|
+
return concat(content, block.binding)
|
187
|
+
end
|
188
|
+
else
|
189
|
+
# this way we're sending an empty string and setting flag stubborn_output_mode of GridOutputBuffer to false
|
190
|
+
return grid.output_buffer.to_s
|
191
|
+
end
|
192
|
+
else
|
193
|
+
return content
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
def generate_blank_slate(grid, rendering) #:nodoc:
|
199
|
+
buff = GridOutputBuffer.new
|
200
|
+
|
201
|
+
buff << if rendering.blank_slate_handler.is_a?(Proc)
|
202
|
+
call_block_as_erb_or_ruby(rendering, rendering.blank_slate_handler, nil)
|
203
|
+
elsif rendering.blank_slate_handler.is_a?(Hash)
|
204
|
+
render(rendering.blank_slate_handler)
|
205
|
+
else
|
206
|
+
rendering.blank_slate_handler
|
207
|
+
end
|
208
|
+
|
209
|
+
if rendering.find_one_for(:in_html){|column| column.detach_with_id}
|
210
|
+
buff.stubborn_output_mode = true
|
211
|
+
buff.return_empty_strings_for_nonexistent_filters = true
|
212
|
+
grid.output_buffer = buff
|
213
|
+
end
|
214
|
+
buff
|
215
|
+
end
|
216
|
+
|
217
|
+
def call_block_as_erb_or_ruby(rendering, block, ar) #:nodoc:
|
218
|
+
if rendering.erb_mode
|
219
|
+
capture(ar, &block)
|
220
|
+
else
|
221
|
+
block.call(ar)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# the longest method? :(
|
226
|
+
def grid_html(grid, options, rendering, reuse_last_column_for_filter_buttons) #:nodoc:
|
227
|
+
|
228
|
+
table_html_attrs, header_tr_html_attrs = options[:table_html_attrs], options[:header_tr_html_attrs]
|
229
|
+
|
230
|
+
cycle_class = nil
|
231
|
+
sorting_dependant_row_cycling = options[:sorting_dependant_row_cycling]
|
232
|
+
|
233
|
+
content = GridOutputBuffer.new
|
234
|
+
# Ruby 1.9.1
|
235
|
+
content.force_encoding('UTF-8') if content.respond_to?(:force_encoding)
|
236
|
+
|
237
|
+
content << %!<div class="wice_grid_container" id="#{grid.name}"><div id="#{grid.name}_title">!
|
238
|
+
content << content_tag(:h3, grid.saved_query.name) if grid.saved_query
|
239
|
+
content << "</div><table #{tag_options(table_html_attrs, true)}>"
|
240
|
+
content << "<thead>"
|
241
|
+
|
242
|
+
no_filters_at_all = (options[:show_filters] == :no || rendering.no_filter_needed?) ? true: false
|
243
|
+
|
244
|
+
if no_filters_at_all
|
245
|
+
no_rightmost_column = no_filter_row = no_filters_at_all
|
246
|
+
else
|
247
|
+
no_rightmost_column = no_filter_row = (options[:show_filters] == :no || rendering.no_filter_needed_in_main_table?) ? true: false
|
248
|
+
end
|
249
|
+
|
250
|
+
no_rightmost_column = true if reuse_last_column_for_filter_buttons
|
251
|
+
|
252
|
+
pagination_panel_content_html, pagination_panel_content_js = nil, nil
|
253
|
+
if options[:upper_pagination_panel]
|
254
|
+
content << rendering.pagination_panel(no_rightmost_column, options[:hide_csv_button]) do
|
255
|
+
pagination_panel_content_html, pagination_panel_content_js =
|
256
|
+
pagination_panel_content(grid, options[:extra_request_parameters], options[:allow_showing_all_records])
|
257
|
+
pagination_panel_content_html
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
title_row_attrs = header_tr_html_attrs.clone
|
262
|
+
title_row_attrs.add_or_append_class_value!('wice_grid_title_row', true)
|
263
|
+
|
264
|
+
content << %!<tr #{tag_options(title_row_attrs, true)}>!
|
265
|
+
|
266
|
+
filter_row_id = grid.name + '_filter_row'
|
267
|
+
|
268
|
+
# first row of column labels with sorting links
|
269
|
+
|
270
|
+
filter_shown = if options[:show_filters] == :when_filtered
|
271
|
+
grid.filtering_on?
|
272
|
+
elsif options[:show_filters] == :always
|
273
|
+
true
|
274
|
+
end
|
275
|
+
|
276
|
+
cached_javascript = []
|
277
|
+
|
278
|
+
rendering.each_column_aware_of_one_last_one(:in_html) do |column, last|
|
279
|
+
|
280
|
+
column_name = column.column_name
|
281
|
+
if column_name.is_a? Array
|
282
|
+
column_name, js = column_name
|
283
|
+
cached_javascript << js
|
284
|
+
end
|
285
|
+
|
286
|
+
if column.attribute_name && column.allow_ordering
|
287
|
+
|
288
|
+
css_class = grid.filtered_by?(column) ? 'active_filter' : nil
|
289
|
+
|
290
|
+
direction = 'asc'
|
291
|
+
link_style = nil
|
292
|
+
if grid.ordered_by?(column)
|
293
|
+
css_class = css_class.nil? ? 'sorted' : css_class + ' sorted'
|
294
|
+
link_style = grid.order_direction
|
295
|
+
direction = 'desc' if grid.order_direction == 'asc'
|
296
|
+
end
|
297
|
+
|
298
|
+
col_link = link_to(column_name,
|
299
|
+
rendering.column_link(column, direction, params, options[:extra_request_parameters]),
|
300
|
+
:class => link_style)
|
301
|
+
content << content_tag(:th, col_link, Hash.make_hash(:class, css_class))
|
302
|
+
column.css_class = css_class
|
303
|
+
else
|
304
|
+
if reuse_last_column_for_filter_buttons && last
|
305
|
+
content << content_tag(:th,
|
306
|
+
hide_show_icon(filter_row_id, grid, filter_shown, no_filter_row, options[:show_filters], rendering),
|
307
|
+
:class => 'hide_show_icon'
|
308
|
+
)
|
309
|
+
else
|
310
|
+
content << content_tag(:th, (column.icon ? image_tag("/images/icons/grid/#{column.icon}", :alt => column_name, :border => 0) : column_name))
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
content << content_tag(:th,
|
316
|
+
hide_show_icon(filter_row_id, grid, filter_shown, no_filter_row, options[:show_filters], rendering),
|
317
|
+
:class => 'hide_show_icon'
|
318
|
+
) unless no_rightmost_column
|
319
|
+
|
320
|
+
content << '</tr>'
|
321
|
+
# rendering first row end
|
322
|
+
|
323
|
+
|
324
|
+
unless no_filters_at_all # there are filters, we don't know where, in the table or detached
|
325
|
+
if no_filter_row # they are all detached
|
326
|
+
content.stubborn_output_mode = true
|
327
|
+
rendering.each_column(:in_html) do |column|
|
328
|
+
if column.filter_shown?
|
329
|
+
filter_html_code, filter_js_code = column.render_filter
|
330
|
+
filter_html_code = filter_html_code.html_safe_if_necessary
|
331
|
+
cached_javascript << filter_js_code
|
332
|
+
content.add_filter(column.detach_with_id, filter_html_code)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
else # some filters are present in the table
|
337
|
+
|
338
|
+
filter_row_attrs = header_tr_html_attrs.clone
|
339
|
+
filter_row_attrs.add_or_append_class_value!('wice_grid_filter_row', true)
|
340
|
+
filter_row_attrs['id'] = filter_row_id
|
341
|
+
|
342
|
+
content << %!<tr #{tag_options(filter_row_attrs, true)} !
|
343
|
+
content << 'style="display:none"' unless filter_shown
|
344
|
+
content << '>'
|
345
|
+
|
346
|
+
rendering.each_column_aware_of_one_last_one(:in_html) do |column, last|
|
347
|
+
if column.filter_shown?
|
348
|
+
filter_html_code, filter_js_code = column.render_filter
|
349
|
+
filter_html_code = filter_html_code.html_safe_if_necessary
|
350
|
+
cached_javascript << filter_js_code
|
351
|
+
if column.detach_with_id
|
352
|
+
content.stubborn_output_mode = true
|
353
|
+
content << content_tag(:th, '', Hash.make_hash(:class, column.css_class))
|
354
|
+
content.add_filter(column.detach_with_id, filter_html_code)
|
355
|
+
else
|
356
|
+
content << content_tag(:th, filter_html_code, Hash.make_hash(:class, column.css_class))
|
357
|
+
end
|
358
|
+
else
|
359
|
+
if reuse_last_column_for_filter_buttons && last
|
360
|
+
content << content_tag(:th,
|
361
|
+
reset_submit_buttons(options, grid, rendering),
|
362
|
+
Hash.make_hash(:class, column.css_class).add_or_append_class_value!('filter_icons')
|
363
|
+
)
|
364
|
+
else
|
365
|
+
content << content_tag(:th, '', Hash.make_hash(:class, column.css_class))
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
unless no_rightmost_column
|
370
|
+
content << content_tag(:th, reset_submit_buttons(options, grid, rendering), :class => 'filter_icons' )
|
371
|
+
end
|
372
|
+
content << '</tr>'
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
rendering.each_column(:in_html) do |column|
|
377
|
+
unless column.css_class.blank?
|
378
|
+
column.td_html_attrs.add_or_append_class_value!(column.css_class)
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
content << '</thead><tfoot>'
|
383
|
+
|
384
|
+
content << rendering.pagination_panel(no_rightmost_column, options[:hide_csv_button]) do
|
385
|
+
if pagination_panel_content_html
|
386
|
+
pagination_panel_content_html
|
387
|
+
else
|
388
|
+
pagination_panel_content_html, pagination_panel_content_js =
|
389
|
+
pagination_panel_content(grid, options[:extra_request_parameters], options[:allow_showing_all_records])
|
390
|
+
pagination_panel_content_html
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
content << '</tfoot><tbody>'
|
395
|
+
cached_javascript << pagination_panel_content_js
|
396
|
+
|
397
|
+
# rendering rows
|
398
|
+
cell_value_of_the_ordered_column = nil
|
399
|
+
previous_cell_value_of_the_ordered_column = nil
|
400
|
+
|
401
|
+
grid.each do |ar| # rows
|
402
|
+
|
403
|
+
before_row_output = if rendering.before_row_handler
|
404
|
+
call_block_as_erb_or_ruby(rendering, rendering.before_row_handler, ar)
|
405
|
+
else
|
406
|
+
nil
|
407
|
+
end
|
408
|
+
|
409
|
+
after_row_output = if rendering.after_row_handler
|
410
|
+
call_block_as_erb_or_ruby(rendering, rendering.after_row_handler, ar)
|
411
|
+
else
|
412
|
+
nil
|
413
|
+
end
|
414
|
+
|
415
|
+
row_content = ''
|
416
|
+
rendering.each_column(:in_html) do |column|
|
417
|
+
cell_block = column.cell_rendering_block
|
418
|
+
|
419
|
+
opts = column.td_html_attrs.clone
|
420
|
+
|
421
|
+
column_block_output = if column.class == Wice::ActionViewColumn
|
422
|
+
cell_block.call(ar, params)
|
423
|
+
else
|
424
|
+
call_block_as_erb_or_ruby(rendering, cell_block, ar)
|
425
|
+
end
|
426
|
+
|
427
|
+
if column_block_output.kind_of?(Array)
|
428
|
+
|
429
|
+
unless column_block_output.size == 2
|
430
|
+
raise WiceGridArgumentError.new('When WiceGrid column block returns an array it is expected to contain 2 elements only - '+
|
431
|
+
'the first is the contents of the table cell and the second is a hash containing HTML attributes for the <td> tag.')
|
432
|
+
end
|
433
|
+
|
434
|
+
column_block_output, additional_opts = column_block_output
|
435
|
+
|
436
|
+
unless additional_opts.is_a?(Hash)
|
437
|
+
raise WiceGridArgumentError.new('When WiceGrid column block returns an array its second element is expected to be a ' +
|
438
|
+
"hash containing HTML attributes for the <td> tag. The returned value is #{additional_opts.inspect}. Read documentation.")
|
439
|
+
end
|
440
|
+
|
441
|
+
additional_css_class = nil
|
442
|
+
if additional_opts.has_key?(:class)
|
443
|
+
additional_css_class = additional_opts[:class]
|
444
|
+
additional_opts.delete(:class)
|
445
|
+
elsif additional_opts.has_key?('class')
|
446
|
+
additional_css_class = additional_opts['class']
|
447
|
+
additional_opts.delete('class')
|
448
|
+
end
|
449
|
+
opts.merge!(additional_opts)
|
450
|
+
opts.add_or_append_class_value!(additional_css_class) unless additional_css_class.blank?
|
451
|
+
end
|
452
|
+
|
453
|
+
if sorting_dependant_row_cycling && column.attribute_name && grid.ordered_by?(column)
|
454
|
+
cell_value_of_the_ordered_column = column_block_output
|
455
|
+
end
|
456
|
+
row_content += content_tag(:td, column_block_output, opts)
|
457
|
+
end
|
458
|
+
|
459
|
+
row_attributes = rendering.get_row_attributes(ar)
|
460
|
+
|
461
|
+
if sorting_dependant_row_cycling
|
462
|
+
cycle_class = cycle('odd', 'even', :name => grid.name) if cell_value_of_the_ordered_column != previous_cell_value_of_the_ordered_column
|
463
|
+
previous_cell_value_of_the_ordered_column = cell_value_of_the_ordered_column
|
464
|
+
else
|
465
|
+
cycle_class = cycle('odd', 'even', :name => grid.name)
|
466
|
+
end
|
467
|
+
|
468
|
+
row_attributes.add_or_append_class_value!(cycle_class)
|
469
|
+
|
470
|
+
content << before_row_output if before_row_output
|
471
|
+
content << "<tr #{tag_options(row_attributes)}>#{row_content}"
|
472
|
+
content << content_tag(:td, '') unless no_rightmost_column
|
473
|
+
content << '</tr>'
|
474
|
+
content << after_row_output if after_row_output
|
475
|
+
end
|
476
|
+
|
477
|
+
content << '</tbody></table></div>'
|
478
|
+
|
479
|
+
content << link_to( "More ▼".html_safe, rendering.more_link(controller, options[:extra_request_parameters]), :id => 'more') if grid.has_more_to_show?
|
480
|
+
|
481
|
+
base_link_for_filter, base_link_for_show_all_records = rendering.base_link_for_filter(controller, options[:extra_request_parameters])
|
482
|
+
|
483
|
+
link_for_export = rendering.link_for_export(controller, 'csv', options[:extra_request_parameters])
|
484
|
+
|
485
|
+
parameter_name_for_query_loading = {grid.name => {:q => ''}}.to_query
|
486
|
+
parameter_name_for_focus = {grid.name => {:foc => ''}}.to_query
|
487
|
+
|
488
|
+
prototype_and_js_version_check = if ENV['RAILS_ENV'] == 'development'
|
489
|
+
%$ if (typeof(WiceGridProcessor) == "undefined"){\n$ +
|
490
|
+
%$ alert('wice_grid.js not loaded, WiceGrid cannot proceed! ' +\n$ +
|
491
|
+
%$ 'Please make sure that you include WiceGrid javascript in your page. ' +\n$ +
|
492
|
+
%$ 'Use <%= include_wice_grid_assets %> or <%= include_wice_grid_assets(:include_calendar => true) %> ' +\n$ +
|
493
|
+
%$ 'for WiceGrid javascripts and assets.')\n$ +
|
494
|
+
%$ } else if ((typeof(WiceGridProcessor._version) == "undefined") || ( WiceGridProcessor._version != "0.4.3")) {\n$ +
|
495
|
+
%$ alert("wice_grid.js in your /public is outdated, please run\\n ./script/generate wice_grid_assets_jquery\\n$ +
|
496
|
+
%$ or\\n ./script/generate wice_grid_assets_prototype\\nto update it.");\n$ +
|
497
|
+
%$ }\n$
|
498
|
+
else
|
499
|
+
''
|
500
|
+
end
|
501
|
+
|
502
|
+
if rendering.show_hide_button_present
|
503
|
+
cached_javascript << JsAdaptor.show_hide_button_initialization(grid.name, filter_row_id)
|
504
|
+
end
|
505
|
+
|
506
|
+
if rendering.reset_button_present
|
507
|
+
cached_javascript << JsAdaptor.reset_button_initialization(grid.name, reset_grid_javascript(grid))
|
508
|
+
end
|
509
|
+
|
510
|
+
if rendering.submit_button_present
|
511
|
+
cached_javascript << JsAdaptor.submit_button_initialization(grid.name, submit_grid_javascript(grid))
|
512
|
+
end
|
513
|
+
|
514
|
+
if rendering.contains_a_text_input?
|
515
|
+
cached_javascript << JsAdaptor.enter_key_event_registration(grid.name)
|
516
|
+
end
|
517
|
+
|
518
|
+
if rendering.csv_export_icon_present
|
519
|
+
cached_javascript << JsAdaptor.csv_export_icon_initialization(grid.name)
|
520
|
+
end
|
521
|
+
|
522
|
+
if rendering.contains_auto_reloading_selects
|
523
|
+
cached_javascript << JsAdaptor.auto_reloading_selects_event_initialization(grid.name)
|
524
|
+
end
|
525
|
+
|
526
|
+
if rendering.contains_auto_reloading_inputs
|
527
|
+
cached_javascript << JsAdaptor.auto_reloading_inputs_event_initialization(grid.name)
|
528
|
+
end
|
529
|
+
|
530
|
+
if rendering.contains_auto_reloading_inputs_with_negation_checkboxes
|
531
|
+
cached_javascript << JsAdaptor.auto_reloading_inputs_with_negation_checkboxes_event_initialization(grid.name)
|
532
|
+
end
|
533
|
+
|
534
|
+
if rendering.contains_auto_reloading_calendars
|
535
|
+
cached_javascript << JsAdaptor.auto_reloading_calendar_event_initialization(grid.name)
|
536
|
+
end
|
537
|
+
|
538
|
+
if rendering.element_to_focus
|
539
|
+
cached_javascript << JsAdaptor.focus_element(rendering.element_to_focus)
|
540
|
+
end
|
541
|
+
|
542
|
+
content << javascript_tag(
|
543
|
+
JsAdaptor.dom_loaded +
|
544
|
+
%/ #{prototype_and_js_version_check}\n/ +
|
545
|
+
%/ window['#{grid.name}'] = new WiceGridProcessor('#{grid.name}', '#{base_link_for_filter}',\n/ +
|
546
|
+
%/ '#{base_link_for_show_all_records}', '#{link_for_export}', '#{parameter_name_for_query_loading}',\n/ +
|
547
|
+
%/ '#{parameter_name_for_focus}', '#{ENV['RAILS_ENV']}');\n/ +
|
548
|
+
if no_filters_at_all
|
549
|
+
''
|
550
|
+
else
|
551
|
+
rendering.select_for(:in_html) do |vc|
|
552
|
+
vc.attribute_name and not vc.no_filter
|
553
|
+
end.collect{|column| column.yield_javascript}.join("\n")
|
554
|
+
end +
|
555
|
+
"\n" + cached_javascript.compact.join('') +
|
556
|
+
'})'
|
557
|
+
)
|
558
|
+
|
559
|
+
if content.stubborn_output_mode
|
560
|
+
grid.output_buffer = content
|
561
|
+
else
|
562
|
+
# this will serve as a flag that the grid helper has already processed the grid but in a normal mode,
|
563
|
+
# not in the mode with detached filters.
|
564
|
+
grid.output_buffer = true
|
565
|
+
end
|
566
|
+
return content
|
567
|
+
end
|
568
|
+
|
569
|
+
def hide_show_icon(filter_row_id, grid, filter_shown, no_filter_row, show_filters, rendering) #:nodoc:
|
570
|
+
grid_name = grid.name
|
571
|
+
no_filter_opening_closing_icon = (show_filters == :always) || no_filter_row
|
572
|
+
|
573
|
+
styles = ["display: block;", "display: none;"]
|
574
|
+
styles.reverse! unless filter_shown
|
575
|
+
|
576
|
+
|
577
|
+
if no_filter_opening_closing_icon
|
578
|
+
hide_icon = show_icon = ''
|
579
|
+
else
|
580
|
+
|
581
|
+
|
582
|
+
rendering.show_hide_button_present = true
|
583
|
+
filter_tooltip = WiceGridNlMessageProvider.get_message(:HIDE_FILTER_TOOLTIP)
|
584
|
+
|
585
|
+
hide_icon = content_tag(:span,
|
586
|
+
image_tag(Defaults::SHOW_HIDE_FILTER_ICON,
|
587
|
+
:title => filter_tooltip,
|
588
|
+
:alt => filter_tooltip),
|
589
|
+
:id => grid_name + '_hide_icon',
|
590
|
+
:style => styles[0],
|
591
|
+
:class => 'clickable'
|
592
|
+
)
|
593
|
+
|
594
|
+
|
595
|
+
filter_tooltip = WiceGridNlMessageProvider.get_message(:SHOW_FILTER_TOOLTIP)
|
596
|
+
|
597
|
+
show_icon = content_tag(:span,
|
598
|
+
image_tag(Defaults::SHOW_HIDE_FILTER_ICON,
|
599
|
+
:title => filter_tooltip,
|
600
|
+
:alt => filter_tooltip),
|
601
|
+
:id => grid_name + '_show_icon',
|
602
|
+
:style => styles[1],
|
603
|
+
:class => 'clickable'
|
604
|
+
)
|
605
|
+
|
606
|
+
hide_icon + show_icon
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
def reset_submit_buttons(options, grid, rendering) #:nodoc:
|
611
|
+
(if options[:hide_submit_button]
|
612
|
+
''
|
613
|
+
else
|
614
|
+
rendering.submit_button_present = true
|
615
|
+
filter_tooltip = WiceGridNlMessageProvider.get_message(:FILTER_TOOLTIP)
|
616
|
+
image_tag(Defaults::FILTER_ICON, :title => filter_tooltip, :alt => filter_tooltip, :class => 'submit clickable')
|
617
|
+
end + ' ' +
|
618
|
+
if options[:hide_reset_button]
|
619
|
+
''
|
620
|
+
else
|
621
|
+
rendering.reset_button_present = true
|
622
|
+
filter_tooltip = WiceGridNlMessageProvider.get_message(:RESET_FILTER_TOOLTIP)
|
623
|
+
image_tag(Defaults::RESET_ICON, :title => filter_tooltip, :alt => filter_tooltip, :class => 'reset clickable')
|
624
|
+
end).html_safe_if_necessary
|
625
|
+
end
|
626
|
+
|
627
|
+
# Renders a detached filter. The parameters are:
|
628
|
+
# * +grid+ the WiceGrid object
|
629
|
+
# * +filter_key+ an identifier of the filter specified in the column declaration by parameter +:detach_with_id+
|
630
|
+
def grid_filter(grid, filter_key)
|
631
|
+
unless grid.kind_of? WiceGrid
|
632
|
+
raise WiceGridArgumentError.new("submit_grid_javascript: the parameter must be a WiceGrid instance.")
|
633
|
+
end
|
634
|
+
if grid.output_buffer.nil?
|
635
|
+
raise WiceGridArgumentError.new("grid_filter: You have attempted to run 'grid_filter' before 'grid'. Read about detached filters in the documentation.")
|
636
|
+
end
|
637
|
+
if grid.output_buffer == true
|
638
|
+
raise WiceGridArgumentError.new("grid_filter: You have defined no detached filters, or you try use detached filters with" +
|
639
|
+
":show_filters => :no (set :show_filters to :always in this case). Read about detached filters in the documentation.")
|
640
|
+
end
|
641
|
+
|
642
|
+
content_tag :span, grid.output_buffer.filter_for(filter_key), :class => "#{grid.name}_detached_filter"
|
643
|
+
end
|
644
|
+
|
645
|
+
# Returns javascript which applies current filters. The parameter is a WiceGrid instance. Use it with +button_to_function+ to create
|
646
|
+
# your Submit button.
|
647
|
+
def submit_grid_javascript(grid)
|
648
|
+
unless grid.kind_of? WiceGrid
|
649
|
+
raise WiceGridArgumentError.new("submit_grid_javascript: the parameter must be a WiceGrid instance.")
|
650
|
+
end
|
651
|
+
"#{grid.name}.process()"
|
652
|
+
end
|
653
|
+
|
654
|
+
# Returns javascript which resets the grid, clearing the state of filters.
|
655
|
+
# The parameter is a WiceGrid instance. Use it with +button_to_function+ to create
|
656
|
+
# your Reset button.
|
657
|
+
def reset_grid_javascript(grid)
|
658
|
+
unless grid.kind_of? WiceGrid
|
659
|
+
raise WiceGridArgumentError.new("reset_grid_javascript: the parameter must be a WiceGrid instance.")
|
660
|
+
end
|
661
|
+
"#{grid.name}.reset()"
|
662
|
+
end
|
663
|
+
|
664
|
+
# Returns javascript which triggers export to CSV.
|
665
|
+
# The parameter is a WiceGrid instance. Use it with +button_to_function+ to create
|
666
|
+
# your own Export To CSV button.
|
667
|
+
def export_to_csv_javascript(grid)
|
668
|
+
unless grid.kind_of? WiceGrid
|
669
|
+
raise WiceGridArgumentError.new("export_csv_javascript: the parameter must be a WiceGrid instance.")
|
670
|
+
end
|
671
|
+
"#{grid.name}.export_to_csv()"
|
672
|
+
end
|
673
|
+
|
674
|
+
|
675
|
+
def grid_csv(grid, rendering) #:nodoc:
|
676
|
+
field_separator = (grid.export_to_csv_enabled && grid.export_to_csv_enabled.is_a?(String)) ? grid.export_to_csv_enabled : ','
|
677
|
+
spreadsheet = ::Wice::Spreadsheet.new(grid.name, field_separator)
|
678
|
+
|
679
|
+
# columns
|
680
|
+
spreadsheet << rendering.column_labels(:in_csv)
|
681
|
+
|
682
|
+
# rendering rows
|
683
|
+
grid.each do |ar| # rows
|
684
|
+
row = []
|
685
|
+
|
686
|
+
rendering.each_column(:in_csv) do |column|
|
687
|
+
cell_block = column.cell_rendering_block
|
688
|
+
|
689
|
+
column_block_output = call_block_as_erb_or_ruby(rendering, cell_block, ar)
|
690
|
+
|
691
|
+
if column_block_output.kind_of?(Array)
|
692
|
+
column_block_output, additional_opts = column_block_output
|
693
|
+
end
|
694
|
+
|
695
|
+
row << column_block_output
|
696
|
+
end
|
697
|
+
spreadsheet << row
|
698
|
+
end
|
699
|
+
grid.csv_tempfile = spreadsheet.tempfile
|
700
|
+
return grid.csv_tempfile.path
|
701
|
+
end
|
702
|
+
|
703
|
+
def pagination_panel_content(grid, extra_request_parameters, allow_showing_all_records) #:nodoc:
|
704
|
+
extra_request_parameters = extra_request_parameters.clone
|
705
|
+
if grid.saved_query
|
706
|
+
extra_request_parameters["#{grid.name}[q]"] = grid.saved_query.id
|
707
|
+
end
|
708
|
+
|
709
|
+
html, js = pagination_info(grid, allow_showing_all_records)
|
710
|
+
'<div class="pagination_status">' + html + '</div>'
|
711
|
+
|
712
|
+
# [will_paginate(grid.resultset,
|
713
|
+
# :previous_label => WiceGridNlMessageProvider.get_message(:PREVIOUS_LABEL),
|
714
|
+
# :next_label => WiceGridNlMessageProvider.get_message(:NEXT_LABEL),
|
715
|
+
# :param_name => "#{grid.name}[page]",
|
716
|
+
# :params => extra_request_parameters).to_s +
|
717
|
+
# (' <div class="pagination_status">' + html + '</div>').html_safe_if_necessary, js]
|
718
|
+
end
|
719
|
+
|
720
|
+
|
721
|
+
def show_all_link(collection_total_entries, parameters, grid_name) #:nodoc:
|
722
|
+
|
723
|
+
message = WiceGridNlMessageProvider.get_message(:ALL_QUERIES_WARNING)
|
724
|
+
confirmation = collection_total_entries > Defaults::START_SHOWING_WARNING_FROM ? "if (confirm('#{message}'))" : ''
|
725
|
+
|
726
|
+
js = JsAdaptor.show_all_link_initialization(grid_name, confirmation, parameters.to_json)
|
727
|
+
|
728
|
+
tooltip = WiceGridNlMessageProvider.get_message(:SHOW_ALL_RECORDS_TOOLTIP)
|
729
|
+
html = %/<span class="show_all_link"><a href="#" title="#{tooltip}">/ +
|
730
|
+
WiceGridNlMessageProvider.get_message(:SHOW_ALL_RECORDS_LABEL) +
|
731
|
+
'</a></span>'
|
732
|
+
|
733
|
+
[html, js]
|
734
|
+
end
|
735
|
+
|
736
|
+
def back_to_pagination_link(parameters, grid_name) #:nodoc:
|
737
|
+
pagination_override_parameter_name = "#{grid_name}[pp]"
|
738
|
+
parameters = parameters.reject{|k, v| k == pagination_override_parameter_name}
|
739
|
+
|
740
|
+
js = JsAdaptor.back_to_pagination_link_initialization(grid_name, parameters.to_json)
|
741
|
+
|
742
|
+
tooltip = WiceGridNlMessageProvider.get_message(:SWITCH_BACK_TO_PAGINATED_MODE_TOOLTIP)
|
743
|
+
html = %/ <span class="show_all_link"><a href="#" title="#{tooltip}">/ +
|
744
|
+
WiceGridNlMessageProvider.get_message(:SWITCH_BACK_TO_PAGINATED_MODE_LABEL) +
|
745
|
+
'</a></span>'
|
746
|
+
[html, js]
|
747
|
+
end
|
748
|
+
|
749
|
+
def pagination_info(grid, allow_showing_all_records) #:nodoc:
|
750
|
+
found = grid.resultset.count
|
751
|
+
total = grid.klass.count
|
752
|
+
shown = [found, grid.status[:per_page].to_i].min
|
753
|
+
summary = ""
|
754
|
+
summary << "Shown: #{shown}"
|
755
|
+
summary << ", Found: #{found}" if grid.has_any_filter_criteria?
|
756
|
+
summary << ", Total: #{total}"
|
757
|
+
[summary, ""]
|
758
|
+
end
|
759
|
+
|
760
|
+
end
|
761
|
+
end
|