mongoid_wice_grid 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|