pluginaweek-table_helper 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +45 -0
- data/LICENSE +20 -0
- data/README.rdoc +171 -0
- data/Rakefile +96 -0
- data/init.rb +1 -0
- data/lib/table_helper.rb +211 -0
- data/lib/table_helper/body.rb +113 -0
- data/lib/table_helper/body_row.rb +74 -0
- data/lib/table_helper/cell.rb +60 -0
- data/lib/table_helper/collection_table.rb +138 -0
- data/lib/table_helper/footer.rb +52 -0
- data/lib/table_helper/header.rb +109 -0
- data/lib/table_helper/html_element.rb +42 -0
- data/lib/table_helper/row.rb +110 -0
- data/test/app_root/app/models/person.rb +2 -0
- data/test/app_root/db/migrate/001_create_people.rb +11 -0
- data/test/helpers/table_helper_test.rb +45 -0
- data/test/test_helper.rb +14 -0
- data/test/unit/body_row_test.rb +155 -0
- data/test/unit/body_test.rb +299 -0
- data/test/unit/cell_test.rb +126 -0
- data/test/unit/collection_table_test.rb +228 -0
- data/test/unit/footer_test.rb +110 -0
- data/test/unit/header_test.rb +270 -0
- data/test/unit/html_element_test.rb +74 -0
- data/test/unit/row_builder_test.rb +55 -0
- data/test/unit/row_test.rb +204 -0
- metadata +96 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'table_helper/body_row'
|
2
|
+
|
3
|
+
module TableHelper
|
4
|
+
# Represents the body of the table. In HTML, you can think of this as
|
5
|
+
# the <tbody> tag of the table.
|
6
|
+
class Body < HtmlElement
|
7
|
+
# The css class to apply for all rows in the body
|
8
|
+
cattr_accessor :empty_caption_class
|
9
|
+
@@empty_caption_class = 'ui-collection-empty'
|
10
|
+
|
11
|
+
# The table this body is a part of
|
12
|
+
attr_reader :table
|
13
|
+
|
14
|
+
# If set to :odd or :even, every odd or even-numbered row will have the
|
15
|
+
# alternate class appended to its html attributes. Default is nil.
|
16
|
+
attr_accessor :alternate
|
17
|
+
|
18
|
+
# The caption to display in the collection is empty
|
19
|
+
attr_accessor :empty_caption
|
20
|
+
|
21
|
+
def initialize(table) #:nodoc:
|
22
|
+
super()
|
23
|
+
|
24
|
+
@table = table
|
25
|
+
@empty_caption = 'No matches found.'
|
26
|
+
end
|
27
|
+
|
28
|
+
def alternate=(value) #:nodoc:
|
29
|
+
raise ArgumentError, 'alternate must be set to :odd or :even' if value && ![:odd, :even].include?(value)
|
30
|
+
@alternate = value
|
31
|
+
end
|
32
|
+
|
33
|
+
# Builds the body of the table. This includes the actual data that is
|
34
|
+
# generated for each object in the collection.
|
35
|
+
#
|
36
|
+
# +each+ expects a block that defines the data in each cell. Each
|
37
|
+
# iteration of the block will provide the row within the table, the object
|
38
|
+
# being rendered, and the index of the object. For example,
|
39
|
+
#
|
40
|
+
# t.rows.each do |row, post, index|
|
41
|
+
# row.title "<div class=\"wrapped\">#{post.title}</div>"
|
42
|
+
# row.category post.category.name
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# In addition, to specifying the data, you can also modify the html
|
46
|
+
# options of the row. For more information on doing this, see the
|
47
|
+
# BodyRow class.
|
48
|
+
#
|
49
|
+
# If the collection is empty and +empty_caption+ is set on the body,
|
50
|
+
# then the actual body will be replaced by a single row containing the
|
51
|
+
# html that was stored in +empty_caption+.
|
52
|
+
#
|
53
|
+
# == Default Values
|
54
|
+
#
|
55
|
+
# Whenever possible, the default value of a cell will be set to the
|
56
|
+
# object's attribute with the same name as the cell. For example,
|
57
|
+
# if a Post consists of the attribute +title+, then the cell for the
|
58
|
+
# title will be prepopulated with that attribute's value:
|
59
|
+
#
|
60
|
+
# t.rows.each do |row, post index|
|
61
|
+
# row.title post.title
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# <tt>row.title</tt> is already set to post.category so there's no need to
|
65
|
+
# manually set the value of that cell. However, it is always possible
|
66
|
+
# to override the default value like so:
|
67
|
+
#
|
68
|
+
# t.rows.each do |row, post, index|
|
69
|
+
# row.title link_to(post.title, post_url(post))
|
70
|
+
# row.category post.category.name
|
71
|
+
# end
|
72
|
+
def each(&block)
|
73
|
+
@builder = block
|
74
|
+
end
|
75
|
+
|
76
|
+
# Builds a row for an object in the table.
|
77
|
+
#
|
78
|
+
# The provided block should set the values for each cell in the row.
|
79
|
+
def build_row(object, index = table.collection.index(object))
|
80
|
+
row = BodyRow.new(object, self)
|
81
|
+
row.alternate = alternate ? index.send("#{alternate}?") : false
|
82
|
+
@builder.call(row.builder, object, index) if @builder
|
83
|
+
row.html
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
def tag_name
|
88
|
+
'tbody'
|
89
|
+
end
|
90
|
+
|
91
|
+
def content
|
92
|
+
content = ''
|
93
|
+
|
94
|
+
if table.empty? && @empty_caption
|
95
|
+
# No objects to display
|
96
|
+
row = Row.new(self)
|
97
|
+
row[:class] = empty_caption_class
|
98
|
+
|
99
|
+
html_options = {}
|
100
|
+
html_options[:colspan] = table.header.columns.size if table.header.columns.size > 1
|
101
|
+
row.cell nil, @empty_caption, html_options
|
102
|
+
|
103
|
+
content << row.html
|
104
|
+
else
|
105
|
+
table.collection.each_with_index do |object, i|
|
106
|
+
content << build_row(object, i)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
content
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'table_helper/row'
|
2
|
+
|
3
|
+
module TableHelper
|
4
|
+
# Represents a single row within the body of a table. The row can consist
|
5
|
+
# of either data cells or header cells.
|
6
|
+
#
|
7
|
+
# == Alternating rows
|
8
|
+
#
|
9
|
+
# Alternating rows can be automated by setting the +alternate+ property.
|
10
|
+
# For example,
|
11
|
+
#
|
12
|
+
# r = BodyRow.new(object, parent)
|
13
|
+
# r.alternate = true
|
14
|
+
class BodyRow < Row
|
15
|
+
# The css class to apply for all rows in the body
|
16
|
+
cattr_accessor :result_class
|
17
|
+
@@result_class = 'ui-collection-result'
|
18
|
+
|
19
|
+
# The css class to apply for rows that are marked as "alternate"
|
20
|
+
cattr_accessor :alternate_class
|
21
|
+
@@alternate_class = 'ui-state-alternate'
|
22
|
+
|
23
|
+
# True if this is an alternating row, otherwise false. Default is false.
|
24
|
+
attr_accessor :alternate
|
25
|
+
|
26
|
+
def initialize(object, parent) #:nodoc:
|
27
|
+
super(parent)
|
28
|
+
|
29
|
+
@alternate = false
|
30
|
+
self[:class] = "#{self[:class]} #{table.object_name} #{result_class}".strip
|
31
|
+
|
32
|
+
# For each column defined in the table, see if we can prepopulate the
|
33
|
+
# cell based on the data in the object. If not, we can at least
|
34
|
+
# provide shortcut accessors to the cell
|
35
|
+
table.header.column_names.each do |column|
|
36
|
+
value = object.respond_to?(column) ? object.send(column) : nil
|
37
|
+
cell(column, value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Generates the html for this row in additional to the border row
|
42
|
+
# (if specified)
|
43
|
+
def html
|
44
|
+
original_options = @html_options.dup
|
45
|
+
self[:class] = "#{self[:class]} #{alternate_class}".strip if alternate
|
46
|
+
html = super
|
47
|
+
@html_options = original_options
|
48
|
+
html
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
# Builds the row's cells based on the order of the columns in the
|
53
|
+
# header. If a cell cannot be found for a specific column, then a blank
|
54
|
+
# cell is rendered.
|
55
|
+
def content
|
56
|
+
number_to_skip = 0 # Keeps track of the # of columns to skip
|
57
|
+
|
58
|
+
html = ''
|
59
|
+
table.header.column_names.each do |column|
|
60
|
+
number_to_skip -= 1 and next if number_to_skip > 0
|
61
|
+
|
62
|
+
if cell = @cells[column]
|
63
|
+
number_to_skip = (cell[:colspan] || 1) - 1
|
64
|
+
else
|
65
|
+
cell = Cell.new(column, nil)
|
66
|
+
end
|
67
|
+
|
68
|
+
html << cell.html
|
69
|
+
end
|
70
|
+
|
71
|
+
html
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module TableHelper
|
2
|
+
# Represents a single cell within a table. This can either be a regular
|
3
|
+
# data cell (td) or a header cell (th). By default, all cells will have
|
4
|
+
# their name appended to the cell's class attribute.
|
5
|
+
#
|
6
|
+
# == Examples
|
7
|
+
#
|
8
|
+
# # Data cell
|
9
|
+
# c = Cell.new(:author, 'John Doe')
|
10
|
+
# c.html # => <td class="author">John Doe</td>
|
11
|
+
#
|
12
|
+
# # Header cell
|
13
|
+
# c = Cell.new(:author, 'Author Name')
|
14
|
+
# c.content_type = :header
|
15
|
+
# c.html
|
16
|
+
#
|
17
|
+
# # With namespace
|
18
|
+
# c = Cell.new(:author, :namespace => 'post')
|
19
|
+
# c.content_type = :header
|
20
|
+
# c.html # => <td class="post-author">Author</td>
|
21
|
+
class Cell < HtmlElement
|
22
|
+
# The css class to apply to empty cells
|
23
|
+
cattr_accessor :empty_class
|
24
|
+
@@empty_class = 'ui-state-empty'
|
25
|
+
|
26
|
+
# The content to display within the cell
|
27
|
+
attr_reader :content
|
28
|
+
|
29
|
+
# The type of content this cell represents (:data or :header)
|
30
|
+
attr_reader :content_type
|
31
|
+
|
32
|
+
def initialize(name, content = name.to_s.titleize, html_options = {}) #:nodoc
|
33
|
+
html_options, content = content, name.to_s.titleize if content.is_a?(Hash)
|
34
|
+
namespace = html_options.delete(:namespace)
|
35
|
+
super(html_options)
|
36
|
+
|
37
|
+
@content = content.to_s
|
38
|
+
|
39
|
+
if name
|
40
|
+
name = "#{namespace}-#{name}" unless namespace.blank?
|
41
|
+
self[:class] = "#{self[:class]} #{name}".strip
|
42
|
+
end
|
43
|
+
self[:class] = "#{self[:class]} #{empty_class}".strip if content.blank?
|
44
|
+
|
45
|
+
self.content_type = :data
|
46
|
+
end
|
47
|
+
|
48
|
+
# Indicates what type of content will be stored in this cell. This can
|
49
|
+
# be set to either :data or :header.
|
50
|
+
def content_type=(value)
|
51
|
+
raise ArgumentError, "content_type must be set to :data or :header, was: #{value.inspect}" unless [:data, :header].include?(value)
|
52
|
+
@content_type = value
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def tag_name
|
57
|
+
@content_type == :data ? 'td' : 'th'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'table_helper/html_element'
|
2
|
+
require 'table_helper/header'
|
3
|
+
require 'table_helper/body'
|
4
|
+
require 'table_helper/footer'
|
5
|
+
|
6
|
+
module TableHelper
|
7
|
+
# Represents a table that displays data for multiple objects within a
|
8
|
+
# collection.
|
9
|
+
class CollectionTable < HtmlElement
|
10
|
+
# The css class to apply for all menu bars
|
11
|
+
cattr_accessor :collection_class
|
12
|
+
@@collection_class = 'ui-collection'
|
13
|
+
|
14
|
+
# The class of objects that will be rendered in the table
|
15
|
+
attr_reader :klass
|
16
|
+
|
17
|
+
# The name of the objects in the collection. By default, this is the
|
18
|
+
# underscored name of the class of objects being rendered. This value is
|
19
|
+
# used for generates parts of the css classes in the table, such as rows
|
20
|
+
# and cells.
|
21
|
+
#
|
22
|
+
# For example, if the class is Post, then the object name will be "post".
|
23
|
+
attr_accessor :object_name
|
24
|
+
|
25
|
+
# The actual collection of objects being rendered in the table's body.
|
26
|
+
# This collection will also be used to help automatically determine what
|
27
|
+
# the class is.
|
28
|
+
attr_reader :collection
|
29
|
+
|
30
|
+
# The body of rows that will be generated for each object in the
|
31
|
+
# collection. The actual content for each row and the html options can
|
32
|
+
# be configured as well.
|
33
|
+
#
|
34
|
+
# See TableHelper::Body for more information.
|
35
|
+
#
|
36
|
+
# == Examples
|
37
|
+
#
|
38
|
+
# # Defining rows
|
39
|
+
# t.rows.each do |row, post, index|
|
40
|
+
# row.category post.category.name
|
41
|
+
# row.author post.author.name
|
42
|
+
# ...
|
43
|
+
# row[:style] = 'margin-top: 5px;'
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # Customizing html options
|
47
|
+
# t.rows[:class] = 'pretty'
|
48
|
+
attr_reader :rows
|
49
|
+
|
50
|
+
# Creates a new table based on the objects within the given collection
|
51
|
+
def initialize(collection, klass = nil, html_options = {}) #:nodoc:
|
52
|
+
html_options, klass = klass, nil if klass.is_a?(Hash)
|
53
|
+
super(html_options)
|
54
|
+
|
55
|
+
@collection = collection
|
56
|
+
@klass = klass || default_class
|
57
|
+
@object_name = @klass ? @klass.name.split('::').last.underscore : nil
|
58
|
+
@html_options.reverse_merge!(:cellspacing => '0', :cellpadding => '0')
|
59
|
+
|
60
|
+
self[:class] = "#{self[:class]} #{@object_name.pluralize}".strip if @object_name
|
61
|
+
self[:class] = "#{self[:class]} #{collection_class}".strip
|
62
|
+
|
63
|
+
# Build actual content
|
64
|
+
@header = Header.new(self)
|
65
|
+
@rows = Body.new(self)
|
66
|
+
@footer = Footer.new(self)
|
67
|
+
|
68
|
+
yield self if block_given?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Will any rows be generated in the table's body?
|
72
|
+
def empty?
|
73
|
+
collection.empty?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Creates a new header cell with the given name. Headers must be defined
|
77
|
+
# in the order in which they will be rendered.
|
78
|
+
#
|
79
|
+
# The actual caption and html options for the header can be configured
|
80
|
+
# as well. The caption determines what will be displayed in each cell.
|
81
|
+
#
|
82
|
+
# == Examples
|
83
|
+
#
|
84
|
+
# # Adding headers
|
85
|
+
# t.header :title # => <th class="post-title">Title</th>
|
86
|
+
# t.header :title, 'The Title' # => <th class="post-title">The Title</th>
|
87
|
+
# t.header :title, :class => 'pretty' # => <th class="post-title pretty">Title</th>
|
88
|
+
# t.header :title, 'The Title', :class => 'pretty' # => <th class="post-title pretty">The Title</th>
|
89
|
+
#
|
90
|
+
# # Customizing html options
|
91
|
+
# t.header[:class] = 'pretty'
|
92
|
+
def header(*args)
|
93
|
+
args.empty? ? @header : @header.column(*args)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Creates a new footer cell with the given name. Footers must be defined
|
97
|
+
# in the order in which they will be rendered.
|
98
|
+
#
|
99
|
+
# The actual caption and html options for the footer can be configured
|
100
|
+
# as well. The caption determines what will be displayed in each cell.
|
101
|
+
#
|
102
|
+
# == Examples
|
103
|
+
#
|
104
|
+
# # Adding footers
|
105
|
+
# t.footer :total # => <td class="post-total"></th>
|
106
|
+
# t.footer :total, 5 # => <td class="post-total">5</th>
|
107
|
+
# t.footer :total, :class => 'pretty' # => <td class="post-total pretty"></th>
|
108
|
+
# t.footer :total, 5, :class => 'pretty' # => <td class="post-total pretty">5</th>
|
109
|
+
#
|
110
|
+
# # Customizing html options
|
111
|
+
# t.footer[:class] = 'pretty'
|
112
|
+
def footer(*args)
|
113
|
+
args.empty? ? @footer : @footer.cell(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
# Finds the class representing the objects within the collection
|
118
|
+
def default_class
|
119
|
+
if collection.respond_to?(:proxy_reflection)
|
120
|
+
collection.proxy_reflection.klass
|
121
|
+
elsif !collection.empty?
|
122
|
+
collection.first.class
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def tag_name
|
127
|
+
'table'
|
128
|
+
end
|
129
|
+
|
130
|
+
def content
|
131
|
+
content = ''
|
132
|
+
content << @header.html unless @header.empty?
|
133
|
+
content << @rows.html
|
134
|
+
content << @footer.html unless @footer.empty?
|
135
|
+
content
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'table_helper/row'
|
2
|
+
|
3
|
+
module TableHelper
|
4
|
+
# Represents the header of the table. In HTML, you can think of this as
|
5
|
+
# the <tfoot> tag of the table.
|
6
|
+
class Footer < HtmlElement
|
7
|
+
# The table this footer is a part of
|
8
|
+
attr_reader :table
|
9
|
+
|
10
|
+
# The actual footer row
|
11
|
+
attr_reader :row
|
12
|
+
|
13
|
+
# Whether or not the footer should be hidden when the collection is
|
14
|
+
# empty. Default is true.
|
15
|
+
attr_accessor :hide_when_empty
|
16
|
+
|
17
|
+
delegate :cell, :empty?, :to => :row
|
18
|
+
|
19
|
+
def initialize(table) #:nodoc:
|
20
|
+
super()
|
21
|
+
|
22
|
+
@table = table
|
23
|
+
@row = Row.new(self)
|
24
|
+
@hide_when_empty = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def html #:nodoc:
|
28
|
+
# Force the last cell to span the remaining columns
|
29
|
+
cells = row.cells.values
|
30
|
+
colspan = table.header.columns.length - cells[0..-2].inject(0) {|count, (name, cell)| count += (cell[:colspan] || 1).to_i}
|
31
|
+
cells.last[:colspan] ||= colspan if colspan > 1
|
32
|
+
|
33
|
+
html_options = @html_options.dup
|
34
|
+
html_options[:style] = "display: none; #{html_options[:style]}".strip if table.empty? && hide_when_empty
|
35
|
+
|
36
|
+
content_tag(tag_name, content, html_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def tag_name
|
41
|
+
'tfoot'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Generates the html for the footer. The footer generally consists of a
|
45
|
+
# summary of the data in the body. This row will be wrapped inside of
|
46
|
+
# a tfoot tag. If the collection is empty and hide_when_empty was set
|
47
|
+
# to true, then the footer will be hidden.
|
48
|
+
def content
|
49
|
+
@row.html
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'table_helper/row'
|
2
|
+
|
3
|
+
module TableHelper
|
4
|
+
# Represents the header of the table. In HTML, you can think of this as
|
5
|
+
# the <thead> tag of the table.
|
6
|
+
class Header < HtmlElement
|
7
|
+
# The table this header is a part of
|
8
|
+
attr_reader :table
|
9
|
+
|
10
|
+
# The actual header row
|
11
|
+
attr_reader :row
|
12
|
+
|
13
|
+
# Whether or not the header should be hidden when the collection is
|
14
|
+
# empty. Default is true.
|
15
|
+
attr_accessor :hide_when_empty
|
16
|
+
|
17
|
+
delegate :empty?, :to => :row
|
18
|
+
|
19
|
+
# Creates a new header for the given table.
|
20
|
+
#
|
21
|
+
# If the class is known, then the header will be pre-filled with
|
22
|
+
# the columns defined in that class (assuming it's an ActiveRecord
|
23
|
+
# class).
|
24
|
+
def initialize(table)
|
25
|
+
super()
|
26
|
+
|
27
|
+
@table = table
|
28
|
+
@row = Row.new(self)
|
29
|
+
@hide_when_empty = true
|
30
|
+
|
31
|
+
# If we know what class the objects in the collection are and we can
|
32
|
+
# figure out what columns are defined in that class, then we can
|
33
|
+
# pre-fill the header with those columns so that the user doesn't
|
34
|
+
# have to
|
35
|
+
klass = table.klass
|
36
|
+
if klass && klass.respond_to?(:column_names)
|
37
|
+
if !table.empty? && klass < ActiveRecord::Base
|
38
|
+
# Make sure only the attributes that have been loaded are used
|
39
|
+
column_names = table.collection.first.attributes.keys
|
40
|
+
else
|
41
|
+
# Assume all attributes are loaded
|
42
|
+
column_names = klass.column_names
|
43
|
+
end
|
44
|
+
|
45
|
+
column(*column_names.map(&:to_sym))
|
46
|
+
end
|
47
|
+
|
48
|
+
@customized = false
|
49
|
+
end
|
50
|
+
|
51
|
+
# The current columns in this header, in the order in which they will be
|
52
|
+
# built
|
53
|
+
def columns
|
54
|
+
row.cells
|
55
|
+
end
|
56
|
+
|
57
|
+
# Gets the names of all of the columns being displayed in the table
|
58
|
+
def column_names
|
59
|
+
row.cell_names
|
60
|
+
end
|
61
|
+
|
62
|
+
# Clears all of the current columns from the header
|
63
|
+
def clear
|
64
|
+
row.clear
|
65
|
+
end
|
66
|
+
|
67
|
+
# Creates one or more to columns in the header. This will clear any
|
68
|
+
# pre-existing columns if it is being customized for the first time after
|
69
|
+
# it was initially created.
|
70
|
+
def column(*names)
|
71
|
+
# Clear the header row if this is being customized by the user
|
72
|
+
unless @customized
|
73
|
+
@customized = true
|
74
|
+
clear
|
75
|
+
end
|
76
|
+
|
77
|
+
# Extract configuration
|
78
|
+
options = names.last.is_a?(Hash) ? names.pop : {}
|
79
|
+
content = names.last.is_a?(String) ? names.pop : nil
|
80
|
+
args = [content, options].compact
|
81
|
+
|
82
|
+
names.collect! do |name|
|
83
|
+
column = row.cell(name, *args)
|
84
|
+
column.content_type = :header
|
85
|
+
column[:scope] ||= 'col'
|
86
|
+
column
|
87
|
+
end
|
88
|
+
|
89
|
+
names.length == 1 ? names.first : names
|
90
|
+
end
|
91
|
+
|
92
|
+
# Creates and returns the generated html for the header
|
93
|
+
def html
|
94
|
+
html_options = @html_options.dup
|
95
|
+
html_options[:style] = 'display: none;' if table.empty? && hide_when_empty
|
96
|
+
|
97
|
+
content_tag(tag_name, content, html_options)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def tag_name
|
102
|
+
'thead'
|
103
|
+
end
|
104
|
+
|
105
|
+
def content
|
106
|
+
@row.html
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|