module ScoreCardHelper
def score_card(*args)
options = args.extract_options!
size = args.first
score_card = ScoreCard.new(self, options, size)
yield score_card
score_card.generate
end
end
class ScoreCard
def initialize(view, options={}, size)
@view = view
@options = options
@size = size
@scores = []
end
def score(label, value, options={})
score_count_class = Array(options.delete(:score_count_class)) << "score-count"
precision = options.delete(:precision)
css = Array(options.fetch(:class, []))
if value.is_a?(Numeric)
css << "zero" if value == 0
css << "positive" if value > 0
css << "negative" if value < 0
end
if value.is_a?(Float) && (value.nan? || value.infinite?)
value = "—".html_safe
css << "nan"
elsif precision
value = @view.number_with_precision(value, precision: precision) if precision
end
value = value.to_s.gsub(/\./, '.')
value = options[:prefix] + value if options[:prefix]
value << "#{options[:unit]}" if options[:unit]
@scores << @view.content_tag(:p, :class => css.join(" ")) do
@view.content_tag(:span, value.html_safe, :class => score_count_class.join(" ")) +
@view.content_tag(:span, label, :class => "score-label")
end
nil
end
def fraction(label, numerator, denominator, options={})
return score(label, numerator, options) unless denominator
precision = options.delete(:precision)
if precision
numerator = @view.number_with_precision(numerator, precision: precision)
denominator = @view.number_with_precision(denominator, precision: precision)
end
value = "#{numerator}" +
"/" +
"#{denominator}"
score(label, value.html_safe, options.merge(score_count_class: "fraction"))
end
def percent(label, value, options={})
score(label, value, options.reverse_merge(precision: 0).merge(score_count_class: "percent"))
end
def raw(content=nil, &block)
content = @view.capture(&block) if block_given?
@scores << content
end
def generate
css = ["score"].concat Array(@options.fetch(:class, []))
css << "score-giant" if @size == :giant
css << "score-large" if @size == :large
css << "score-medium" if @size == :medium
css << "score-small" if @size == :small
@view.content_tag(:div, @scores.join.html_safe, @options.slice(:style).merge(:class => css.join(" ")))
end
end