magic_grid 0.12.4 → 0.12.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,131 @@
1
1
  require 'magic_grid/definition'
2
+ require 'magic_grid/order'
2
3
 
3
4
  module MagicGrid
4
5
  class HtmlGrid
6
+ attr_reader :view, :grid
7
+ private :view, :grid
5
8
 
6
9
  def initialize(grid_definition, view, controller = nil)
7
10
  @grid = grid_definition
11
+ @spinner_drawn = false
8
12
  @view ||= view
9
- if controller
10
- @current_url = controller.request.fullpath
11
- else
12
- @current_url = nil
13
- end
13
+ @current_url = controller && controller.request.fullpath
14
14
  end
15
15
 
16
16
  def render(&row_renderer)
17
- @spinner_drawn = false
18
- grid_data = {
19
- :searcher => @grid.searcher,
20
- :current => @current_url,
21
- :live_search => @grid.options[:live_search],
22
- :listeners => @grid.options[:listeners],
23
- :remote => @grid.options[:remote],
24
- :default_ajax_handler => @grid.options[:default_ajax_handler],
25
- :params => @grid.base_params,
26
- }
17
+ @row_renderer = row_renderer || method(:grid_row)
27
18
  table_options = {
28
- :class => (['magic_grid'] << @grid.options[:class]).join(' '),
29
- :id => @grid.magic_id,
30
- :data => grid_data.select {|_,v| v }
19
+ :class => "magic_grid #{grid.options[:class]}",
20
+ :id => grid.magic_id,
21
+ :data => {
22
+ :searcher => grid.searcher,
23
+ :current => @current_url,
24
+ :live_search => grid.options[:live_search],
25
+ :listeners => grid.options[:listeners],
26
+ :remote => grid.options[:remote],
27
+ :default_ajax_handler => grid.options[:default_ajax_handler],
28
+ :params => grid.base_params,
29
+ }.reject {|_,v| v.nil? }
31
30
  }
32
- @view.content_tag('table', table_options) do
33
- thead + tbody(&row_renderer) + tfoot
34
- end
35
- end
36
-
37
- def thead
38
- @view.content_tag('thead', :data => {:params => @grid.base_params}) do
39
- magic_grid_head
40
- end
41
- end
42
-
43
- def tbody(&row_renderer)
44
- @view.content_tag('tbody', :class => "ui-widget-content") do
45
- magic_rows &row_renderer
46
- end
31
+ table(table_options)
47
32
  end
48
33
 
49
- def tfoot
50
- @view.content_tag('tfoot') do
51
- magic_grid_foot
34
+ def table(options)
35
+ view.content_tag('table', options) do
36
+ view.content_tag('thead',
37
+ :data => {:params => grid.base_params},
38
+ &method(:magic_grid_head)) <<
39
+ view.content_tag('tbody',
40
+ :class => "ui-widget-content",
41
+ &method(:magic_rows)) <<
42
+ view.content_tag('tfoot',
43
+ &method(:magic_grid_foot))
52
44
  end
53
45
  end
54
46
 
55
- def spinner_generator
47
+ def render_spinner
56
48
  unless @spinner_drawn
57
49
  @spinner_drawn = true
58
- @view.tag('span',
59
- :id => (@grid.magic_id.to_s + "_spinner"),
50
+ view.tag('span',
51
+ :id => (grid.magic_id.to_s + "_spinner"),
60
52
  :class => "magic_grid_spinner")
61
53
  end
62
54
  end
63
55
 
64
56
  def magic_grid_head
65
- spinner = self.method(:spinner_generator)
66
57
  thead = []
67
- if @grid.needs_searcher?
68
- thead << searcher_block(&spinner)
58
+ if grid.has_title?
59
+ thead << render_title(grid.title)
69
60
  end
70
- if @grid.options[:per_page] and @grid.options[:top_pager]
71
- thead << magic_pager_block(&spinner)
61
+ if grid.needs_searcher?
62
+ thead << searcher_block
72
63
  end
73
- if thead.empty? and not @grid.options[:collapse_emtpy_header]
74
- thead << filler_block(&spinner)
64
+ if grid.options[:per_page] and grid.options[:top_pager]
65
+ thead << magic_pager_block(true)
66
+ end
67
+ if thead.empty? and not grid.options[:collapse_emtpy_header]
68
+ thead << filler_block(&method(:render_spinner))
75
69
  end
76
70
  thead << magic_column_headers
77
71
  thead.join.html_safe
78
72
  end
79
73
 
74
+ def render_title(title)
75
+ view.content_tag 'tr' do
76
+ view.content_tag('th', title,
77
+ :class => 'full-width ui-widget-header',
78
+ :colspan => grid.columns.count)
79
+ end
80
+ end
81
+
80
82
  def magic_grid_foot
81
- if @grid.options[:per_page] and @grid.options[:bottom_pager]
83
+ if grid.options[:per_page] and grid.options[:bottom_pager]
82
84
  magic_pager_block
83
- elsif not @grid.options[:collapse_emtpy_footer]
85
+ elsif not grid.options[:collapse_emtpy_footer]
84
86
  filler_block
85
87
  end
86
88
  end
87
89
 
88
- def filler_block(content = nil, &block)
89
- @view.content_tag 'tr' do
90
- @view.content_tag('td', content,
90
+ def filler_block(&block)
91
+ view.content_tag 'tr' do
92
+ view.content_tag('td', nil,
91
93
  :class => 'full-width ui-widget-header',
92
- :colspan => @grid.columns.count,
94
+ :colspan => grid.columns.count,
93
95
  &block)
94
96
  end
95
97
  end
96
98
 
97
99
  def magic_column_headers
98
- @view.content_tag 'tr' do
99
- @grid.columns.reduce(''.html_safe) do |acc, col|
100
+ view.content_tag 'tr' do
101
+ grid.columns.reduce(''.html_safe) do |acc, col|
100
102
  classes = ['ui-state-default'] << col.html_classes
101
103
  acc <<
102
104
  if col.sortable?
103
105
  sortable_header(col)
104
106
  else
105
- @view.content_tag 'th', col.label.html_safe, :class => classes.join(' ')
107
+ view.content_tag 'th', col.label.html_safe, :class => classes.join(' ')
106
108
  end
107
109
  end
108
110
  end
109
111
  end
110
112
 
111
- def magic_rows(&row_renderer)
112
- rows = @grid.collection.map { |row| grid_row(row, &row_renderer) }
113
+ def magic_rows
114
+ rows = grid.collection.map(&@row_renderer)
113
115
  if rows.empty?
114
- rows << render_empty_collection(@grid.options[:if_empty])
116
+ render_empty_collection(grid.options[:if_empty]).html_safe
117
+ else
118
+ rows.join.html_safe
115
119
  end
116
- rows.join.html_safe
117
120
  end
118
121
 
119
122
  def render_empty_collection(fallback)
120
123
  if fallback
121
- @view.content_tag 'tr' do
122
- @view.content_tag('td', :colspan => @grid.columns.count,
124
+ view.content_tag 'tr' do
125
+ view.content_tag('td', :colspan => grid.columns.count,
123
126
  :class => 'if-empty') do
124
127
  if fallback.respond_to? :call
125
- fallback.call(@grid).to_s
128
+ fallback.call(grid).to_s
126
129
  else
127
130
  fallback
128
131
  end
@@ -131,18 +134,14 @@ module MagicGrid
131
134
  end
132
135
  end
133
136
 
134
- def grid_row(record, &row_renderer)
135
- if row_renderer
136
- @view.capture(record, &row_renderer)
137
- else
138
- @view.content_tag 'tr', :class => @view.cycle('odd', 'even') do
139
- @grid.columns.map { |c| grid_cell(c, record) }.join.html_safe
140
- end
137
+ def grid_row(record)
138
+ view.content_tag 'tr', :class => view.cycle('odd', 'even') do
139
+ grid.columns.map { |c| grid_cell(c, record) }.join.html_safe
141
140
  end
142
141
  end
143
142
 
144
143
  def grid_cell(column, record)
145
- @view.content_tag('td', :class => column.html_classes) do
144
+ view.content_tag('td', :class => column.html_classes) do
146
145
  method = column.reader
147
146
  if method.respond_to? :call
148
147
  method.call(record).to_s
@@ -154,114 +153,86 @@ module MagicGrid
154
153
  end
155
154
  end
156
155
 
157
- def unordered
158
- -1
159
- end
160
-
161
- def reverse_order(order)
162
- order.to_i == 0 ? 1 : 0
163
- end
164
-
165
- def order_icon(order = -1)
166
- @view.content_tag 'span', '', :class => "ui-icon #{order_icon_class(order)}"
156
+ def order_icon(order = Order::Unordered)
157
+ view.content_tag 'span', '', :class => "ui-icon #{order.icon_class}"
167
158
  end
168
159
 
169
- def order_icon_class(order = -1)
170
- case order.to_i
171
- when 0 then 'ui-icon-triangle-1-n'
172
- when 1 then 'ui-icon-triangle-1-s'
173
- else 'ui-icon-carat-2-n-s'
174
- end
175
- end
176
-
177
- def order_class(order = -1)
178
- case order.to_i
179
- when 0 then 'sort-asc'
180
- when 1 then 'sort-desc'
181
- else 'sort-none'
160
+ def column_link_params(col)
161
+ id = col.id
162
+ my_params = grid.base_params.merge(grid.param_key(:col) => id)
163
+ params = HashWithIndifferentAccess.new(my_params)
164
+ if id.to_s == grid.current_sort_col.to_s
165
+ params[grid.param_key(:order)] = grid.current_order.reverse.to_param
166
+ else
167
+ params.delete(grid.param_key(:order))
182
168
  end
169
+ params
183
170
  end
184
171
 
185
172
  def sortable_header(col)
186
173
  id = col.id
187
174
  label = col.label || id.titleize
188
- default_sort_order = @grid.order(@grid.default_order)
189
- my_params = @grid.base_params.merge({
190
- @grid.param_key(:col) => id,
191
- })
192
- column_link_params = HashWithIndifferentAccess.new(my_params)
193
- order = unordered
194
- classes = ['sorter ui-state-default'] << col.html_classes
195
- if id.to_s == @grid.current_sort_col.to_s
196
- order = @grid.current_order
197
- classes << "sort-current" << order_class(order)
198
- column_link_params[@grid.param_key(:order)] = reverse_order(order)
199
- else
200
- column_link_params.delete @grid.param_key(:order)
201
- end
202
- if column_link_params[@grid.param_key(:order)].to_i == default_sort_order.to_i
203
- column_link_params.delete(@grid.param_key(:order))
204
- end
205
- @view.content_tag 'th', :class => classes.join(' ') do
206
- @view.link_to column_link_params, :remote => @grid.options[:remote] do
207
- label.html_safe << order_icon(order)
175
+ params = column_link_params(col)
176
+ classes = %w{sorter ui-state-default} << col.html_classes
177
+ classes << 'sort-current' if col.order.sorted?
178
+ view.content_tag 'th', :class => classes.join(' ') do
179
+ view.link_to params, :remote => grid.options[:remote] do
180
+ label.html_safe << order_icon(col.order)
208
181
  end
209
182
  end
210
183
  end
211
184
 
212
- def searcher_block(&spinner)
213
- @view.content_tag('tr') do
214
- @view.content_tag('td', :class => 'searcher full-width ui-widget-header',
215
- :colspan => @grid.columns.count) do
216
- searcher_input(&spinner)
185
+ def searcher_block
186
+ view.content_tag('tr') do
187
+ view.content_tag('td', :class => 'searcher full-width ui-widget-header',
188
+ :colspan => grid.columns.count) do
189
+ searcher_input
217
190
  end
218
191
  end
219
192
  end
220
193
 
221
- def searcher_input(&spinner)
194
+ def searcher_input
222
195
  searcher_data = {
223
- :min_length => @grid.options[:min_search_length],
224
- :current => @grid.current_search || "",
196
+ :min_length => grid.options[:min_search_length],
197
+ :current => grid.current_search,
225
198
  }
226
- searcher = @view.label_tag(@grid.searcher.to_sym,
227
- @grid.options[:searcher_label])
228
- searcher << @view.search_field_tag(@grid.searcher.to_sym,
229
- @grid.param(:q),
230
- :placeholder => @grid.options[:searcher_tooltip],
231
- :size => @grid.options[:searcher_size],
232
- :data => searcher_data,
233
- :form => "a form that doesn't exist")
234
- if @grid.options[:search_button]
235
- searcher << @view.button_tag(@grid.options[:searcher_button],
236
- :class => 'magic-grid-search-button')
199
+ searcher = view.label_tag(grid.searcher.to_sym,
200
+ grid.options[:searcher_label])
201
+ searcher << view.search_field_tag(grid.searcher.to_sym,
202
+ grid.param(:q),
203
+ :placeholder => grid.options[:searcher_tooltip],
204
+ :size => grid.options[:searcher_size],
205
+ :data => searcher_data,
206
+ :form => "a form that doesn't exist")
207
+ if grid.options[:search_button]
208
+ searcher << view.button_tag(grid.options[:searcher_button],
209
+ :class => 'magic-grid-search-button')
237
210
  end
238
- searcher << yield if block_given?
239
- searcher
211
+ searcher << render_spinner
240
212
  end
241
213
 
242
214
  def magic_pager(collection, opts={})
243
- if @view.respond_to? :will_paginate
215
+ if view.respond_to? :will_paginate
244
216
  # WillPaginate
245
- @view.will_paginate collection.collection, opts
246
- elsif @view.respond_to? :paginate
217
+ view.will_paginate collection.collection, opts
218
+ elsif view.respond_to? :paginate
247
219
  #Kaminari, or something else..
248
- @view.paginate collection.collection, opts
220
+ view.paginate collection.collection, opts
249
221
  else
250
222
  ("<!-- page #{collection.current_page} of #{collection.total_pages} -->" +
251
223
  '<!-- INSTALL WillPaginate or Kaminari for a pager! -->').html_safe
252
224
  end
253
225
  end
254
226
 
255
- def magic_pager_block(&spinner)
256
- @view.content_tag('tr') do
257
- @view.content_tag('td', :class => 'full-width ui-widget-header magic-pager',
258
- :colspan => @grid.columns.count) do
259
- pager = magic_pager(@grid.magic_collection,
260
- :param_name => @grid.param_key(:page),
261
- :params => @grid.base_params
262
- )
227
+ def magic_pager_block(spinner = false)
228
+ view.content_tag('tr') do
229
+ view.content_tag('td', :class => 'full-width ui-widget-header magic-pager',
230
+ :colspan => grid.columns.count) do
231
+ pager = magic_pager(grid.magic_collection,
232
+ :param_name => grid.param_key(:page),
233
+ :params => grid.base_params)
263
234
  if spinner
264
- pager << @view.capture(&spinner)
235
+ pager << render_spinner
265
236
  end
266
237
  pager
267
238
  end
@@ -0,0 +1,69 @@
1
+ module MagicGrid
2
+ module Order
3
+ class Unordered
4
+ def self.css_class
5
+ 'sort-none'
6
+ end
7
+ def self.icon_class
8
+ 'ui-icon-carat-2-n-s'
9
+ end
10
+ def self.to_sql
11
+ 'ASC'
12
+ end
13
+ def self.to_param
14
+ 0
15
+ end
16
+ def self.sorted?
17
+ false
18
+ end
19
+ def self.reverse
20
+ Descending
21
+ end
22
+ end
23
+ class Unsortable < Unordered; end
24
+ class Ascending < Unordered
25
+ def self.css_class
26
+ 'sort-asc'
27
+ end
28
+ def self.icon_class
29
+ 'ui-icon-triangle-1-n'
30
+ end
31
+ def self.sorted?
32
+ true
33
+ end
34
+ def self.reverse
35
+ Descending
36
+ end
37
+ end
38
+ class Descending < Unordered
39
+ def self.css_class
40
+ 'sort-desc'
41
+ end
42
+ def self.icon_class
43
+ 'ui-icon-triangle-1-s'
44
+ end
45
+ def self.to_sql
46
+ 'DESC'
47
+ end
48
+ def self.to_param
49
+ 1
50
+ end
51
+ def self.sorted?
52
+ true
53
+ end
54
+ def self.reverse
55
+ Ascending
56
+ end
57
+ end
58
+ def self.from_param(something)
59
+ case something
60
+ when 1, "1", :desc, :DESC, "desc", "DESC", Descending
61
+ Descending
62
+ #when 0, "0", :asc, :ASC, "asc", "ASC", Ascending
63
+ # Ascending
64
+ else
65
+ Ascending
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module MagicGrid
2
- VERSION = "0.12.4"
2
+ VERSION = "0.12.5"
3
3
  end