require 'table_helper/body_row'
module TableHelper
# Represents the body of the table. In HTML, you can think of this as
# the
tag of the table.
class Body < HtmlElement
# The css class to apply for all rows in the body
cattr_accessor :empty_caption_class
@@empty_caption_class = 'ui-collection-empty'
# The table this body is a part of
attr_reader :table
# If set to :odd or :even, every odd or even-numbered row will have the
# alternate class appended to its html attributes. Default is nil.
attr_accessor :alternate
# The caption to display in the collection is empty
attr_accessor :empty_caption
def initialize(table) #:nodoc:
super()
@table = table
@empty_caption = 'No matches found.'
end
def alternate=(value) #:nodoc:
raise ArgumentError, 'alternate must be set to :odd or :even' if value && ![:odd, :even].include?(value)
@alternate = value
end
# Builds the body of the table. This includes the actual data that is
# generated for each object in the collection.
#
# +each+ expects a block that defines the data in each cell. Each
# iteration of the block will provide the row within the table, the object
# being rendered, and the index of the object. For example,
#
# t.rows.each do |row, post, index|
# row.title "#{post.title}
"
# row.category post.category.name
# end
#
# In addition, to specifying the data, you can also modify the html
# options of the row. For more information on doing this, see the
# BodyRow class.
#
# If the collection is empty and +empty_caption+ is set on the body,
# then the actual body will be replaced by a single row containing the
# html that was stored in +empty_caption+.
#
# == Default Values
#
# Whenever possible, the default value of a cell will be set to the
# object's attribute with the same name as the cell. For example,
# if a Post consists of the attribute +title+, then the cell for the
# title will be prepopulated with that attribute's value:
#
# t.rows.each do |row, post index|
# row.title post.title
# end
#
# row.title is already set to post.category so there's no need to
# manually set the value of that cell. However, it is always possible
# to override the default value like so:
#
# t.rows.each do |row, post, index|
# row.title link_to(post.title, post_url(post))
# row.category post.category.name
# end
def each(&block)
@builder = block
end
# Builds a row for an object in the table.
#
# The provided block should set the values for each cell in the row.
def build_row(object, index = table.collection.index(object))
row = BodyRow.new(object, self)
row.alternate = alternate ? index.send("#{alternate}?") : false
@builder.call(row.builder, object, index) if @builder
row.html
end
private
def tag_name
'tbody'
end
def content
content = ''
if table.empty? && @empty_caption
# No objects to display
row = Row.new(self)
row[:class] = empty_caption_class
html_options = {}
html_options[:colspan] = table.header.columns.size if table.header.columns.size > 1
row.cell nil, @empty_caption, html_options
content << row.html
else
table.collection.each_with_index do |object, i|
content << build_row(object, i)
end
end
content
end
end
end