module CssGraphs
VERSION='0.1.0'
# Makes a vertical bar graph.
#
# bar_graph [["Stout", 10], ["IPA", 80], ["Pale Ale", 50], ["Milkshake", 30]]
#
# NOTE: Updated to take an array instead of forcing you to use *array.
# NOTE: Normalizes data to fit in the viewable area instead of being fixed to 100.
def bar_graph(data=[])
width = 378
height = 150
colors = %w(#ce494a #efba29 #efe708 #5a7dd6 #73a25a)
floor_cutoff = 24 # Pixels beneath which values will not be drawn in graph
data_max = data.inject(0) { |memo, array| array.last > memo ? array.last : memo }
html = <<-"HTML"
HTML
data.each_with_index do |d, index|
scaled_value = scale_graph_value(d.last, data_max, 100)
html += <<-"HTML"
- #{d[0].to_s.humanize}
- #{scaled_value < floor_cutoff ? '' : d.last}
HTML
end
html += <<-"HTML"
HTML
html
end
# Makes a vertical bar graph with several sets of bars.
#
# NOTE: Normalizes data to fit in the viewable area instead of being fixed to 100.
#
# Example:
## <% @data_for_graph = [[['January',10],['February',25],['March',45]],[['January',34],['February',29],['March',80]]] %>
## <%= bar_graph (@data_for_graph,{:width => 640,:height => 480}) do |index,variable|
## url_for( :action => 'report', :month => index)
## end
## %>
#
# alldata should be an array of variables, each one an array itself, of the form:
## [['label1',value1],['label2',value2]]
#
# options hash:
#* :display_value_on_bar if set to true, will display the value on top each bar, default behavior is not to show the value
#* :colors is an array of colors in hex format: '#EEC2D2' if you don't set them, default colors will be used
#* :color_by can be set to 'dimension' or 'index'
#* :width and :height set the dimensions, wich default to 378x150
#
# url_creator_block:
#
## the url_creator_block receives two parameters, index and variable, that are used to build the bars links.
## index is the position for this bar's that in its variable array, while variable is the variable this bar represents
def multi_bar_graph(alldata=[], options={}, &url_creator)
graph_id = (rand*10000000000000000000).to_i.to_s #we need a unique id for each graph on the page so we can have distinct styles for each of them
if !options.nil? && options[:width] && options[:height]
width,height=options[:width].to_i,options[:height].to_i
else
width,height = 378,150
end
colors = (%w(#ce494a #efba29 #efe708 #5a7dd6 #73a25a))*10 unless colors=options[:colors]
floor_cutoff = 24 # Pixels beneath which values will not be drawn in graph
data_max = (alldata.map { |data| data.max{ |a,b| a.last <=> b.last }.last } ).max
dimensions=alldata.size
size = alldata.map{ |data| data.size }.max
bar_offset = 24 #originally set to 24
bar_group_width=(width-bar_offset)/size #originally set to 48px
bar_increment = bar_group_width #originally set to 75
bar_width=(bar_group_width-bar_offset)/dimensions #originally set to 28px
bar_image_offset = bar_offset+4 #originally set to 28
bar_padding = 2
#p "dimensions = #{dimensions}"
#p "bar_group_width =#{bar_group_width}"
#p "bar_width = #{bar_width}"
#p "bar_increment = #{bar_increment}"
html = <<-"HTML"
HTML
alldata.each_with_index do |data,dimension|
# data_max = data.inject(0) { |memo, array| array.last > memo ? array.last : memo }
data.each_with_index do |d, index|
scaled_value = scale_graph_value(d.last, data_max, height-50)
if (options[:display_value_on_bar])
bar_text=(scaled_value < floor_cutoff ? '' : d.last).to_s #text on top of the bar
else
bar_text=''
end
if dimension==0
html += <<-"HTML"
- #{d[0].to_s}
HTML
end
@url = url_creator.call(index,dimension) if !url_creator.nil?
html += <<-"HTML"
- #{bar_text}
HTML
end
end
html += <<-"HTML"
HTML
html
end
# Make a horizontal graph that only shows percentages.
#
# The label will be set as the title of the bar element.
#
# horizontal_bar_graph [["Stout", 10], ["IPA", 80], ["Pale Ale", 50], ["Milkshake", 30]]
#
# NOTE: Updated to take an array instead of forcing you to use *array.
# NOTE: Does not normalize data yet...TODO
def horizontal_bar_graph(data)
html = <<-"HTML"
HTML
data.each do |d|
html += <<-"HTML"
#{d[1]}%
HTML
end
return html
end
# Makes a multi-colored bar graph with a bar down the middle, representing the value.
#
# complex_bar_graph [["Stout", 10], ["IPA", 80], ["Pale Ale", 50], ["Milkshake", 30]]
#
# NOTE: Updated to take an array instead of forcing you to use *array.
# NOTE: Does not normalize data yet...TODO
def complex_bar_graph(data)
html = <<-"HTML"
HTML
data.each do |d|
html += <<-"HTML"
- #{d[0].to_s.humanize}
-
#{d[1]}%
HTML
end
html += "
\n
"
return html
end
##
# Scale values within a +max+. The +max+ will usually be the height of the graph.
def scale_graph_value(data_value, data_max, max)
((data_value.to_f / data_max.to_f) * max).round
end
end