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