module Storefront
class Table
include Storefront::AttributeHelper
include Storefront::LocaleHelper
include Storefront::TimeHelper
attr_reader :content, :template, :key
def initialize(template, *args, &block)
@template = template
options = args.extract_options!
record_or_key = args.shift
@key = record_key(record_or_key)
@row_index = 0
@cell_index = 0
@scope = :table
@headers = []
options[:summary] ||= "Table for #{key.titleize}"
options[:class] = ["data-table", options[:class]].compact.uniq.join(" ")
options[:role] = :grid
data = options.delete(:data) || {}
data[:url] = options[:url] || @template.controller.request.path
data[:for] = options[:for] || options[:model] || @key
data[:total] = options[:total] if options[:total]
data[:page] = options[:page] if options[:page]
data[:count] = options[:count] if options[:count]
aria = options.delete(:aria) || {}
aria[:"aria-multiselectable"] = false unless aria.has_key?(:"aria-multiselectable") || options[:multiselect] == true
options[:data] = data
options[:id] ||= "#{record_or_key.to_s}-table"
@content = template.capture_haml do
template.haml_tag :table, options do
yield(self)
end
end
end
def caption
end
# scope='col'
def head(attributes = {}, &block)
@hide_header = attributes.delete(:visible) == false
template.capture_haml do
@row_index = 0
@scope = :head
template.haml_tag :thead, attributes, &block
@row_index = 0
@scope = :table
end
end
# scope='row'
#
|
def body(attributes = {}, &block)
template.capture_haml do
@row_index = 0
@scope = :body
template.haml_tag :tbody, attributes, &block
@row_index = 0
@scope = :table
end
end
def foot(attributes = {}, &block)
template.capture_haml do
@row_index = 0
@scope = :foot
template.haml_tag :tfoot, attributes, &block
@row_index = 0
@scope = :table
end
end
def row(*args, &block)
attributes = args.extract_options!
if @scope == :body
attributes[:class] = [template.cycle("odd", "even"), attributes[:class]].compact.uniq.join(" ")
end
attributes[:role] = :row
attributes[:scope] = :row
template.capture_haml do
@row_index += 1
@cell_index = 0
template.haml_tag :tr, attributes, &block
@cell_index = 0
end
end
def column(*args, &block)
attributes = args.extract_options!
value = args.shift
attributes[:id] ||= id_for(:header, key, value, @row_index, @cell_index)
[:width, :height].each do |size|
attributes[size] = pixelate(attributes[size]) unless attributes[size].nil?
end
@headers.push(attributes[:id])
template.capture_haml do
template.haml_tag :col, attributes
@cell_index += 1
end
end
# direction => "ascending"
# valid directions: ascending, descending, none, other
# abbr is what the header controls (for sorting)
def header(*args, &block)
attributes = args.extract_options!
value = args.shift
if value.is_a?(::Symbol)
attributes[:abbr] ||= value.to_s
end
# aria-selected if sorted
attributes[:role] = :columnheader
attributes[:id] ||= id_for(:header, key, value, @row_index, @cell_index)
attributes[:scope] = :col
attributes[:abbr] ||= attributes.delete(:for) if attributes.has_key?(:for)
[:width, :height].each do |size|
attributes[size] = pixelate(attributes[size]) unless attributes[size].nil?
end
sort = attributes.delete(:sort) == true
label = attributes.delete(:label) || (value.is_a?(::String) ? value.strip : value.to_s.titleize)
if sort
attributes[:class] = [attributes[:class], attributes.delete(:sort_class) || "sortable"].compact.uniq.join(" ")
attributes[:direction] ||= template.sort_class(value)
end
direction = attributes.delete(:direction)
if direction.present?
attributes[:"aria-sort"] = direction
attributes[:class] = [attributes[:class], direction].join(" ")
attributes[:"aria-selected"] = true
else
attributes[:"aria-sort"] = "none"
attributes[:"aria-selected"] = false
end
@headers.push(attributes[:id])
template.capture_haml do
if block_given?
template.haml_tag :th, attributes, &block
else
if sort
template.haml_tag :th, attributes do
template.haml_concat template.link_to_sort(label, value)
end
else
template.haml_tag :th, label, attributes
end
end
@cell_index += 1
end
end
def cell(*args, &block)
attributes = args.extract_options!
value = args.shift
attributes[:role] = :gridcell
attributes[:id] ||= id_for(:cell, key, value, @row_index, @cell_index)
#attributes[:"aria-describedby"] = @headers[@cell_index]
attributes[:headers] = @headers[@cell_index]
[:width, :height].each do |size|
attributes[size] = pixelate(attributes[size]) unless attributes[size].nil?
end
template.capture_haml do
if block_given?
template.haml_tag :td, attributes, &block
else
template.haml_tag :td, value.to_s.strip, attributes
end
@cell_index += 1
end
end
def record_key(record_or_key)
if record_or_key.is_a?(String) || record_or_key.is_a?(Symbol)
record_or_key.to_s
else
record_or_key.class.name
end
end
def id_for(type, key, value, row_index = @row_index, column_index = @column_index)
[key, type, row_index, column_index].compact.map do |node|
node.to_s.gsub(/[\s_]/, "-")
end.join("-")
end
private
def pixelate(value)
value.is_a?(::String) ? value : "#{value}px"
end
end
end