googlecharts-1.6.12/0000755000004100000410000000000012564736151014324 5ustar www-datawww-datagooglecharts-1.6.12/Rakefile0000644000004100000410000000042612564736151015773 0ustar www-datawww-datarequire 'rspec/core/rake_task' desc 'Default: run specs.' task :default => :spec desc "Run specs" RSpec::Core::RakeTask.new do |task| task.pattern = "**/spec/*_spec.rb" task.rspec_opts = [] task.rspec_opts << '--color' task.rspec_opts << '-f documentation' endgooglecharts-1.6.12/Gemfile0000644000004100000410000000014312564736151015615 0ustar www-datawww-datasource "http://rubygems.org" gemspec group :test do gem 'rspec' gem 'rake', '>= 0.8.7' end googlecharts-1.6.12/License.txt0000644000004100000410000000204112564736151016444 0ustar www-datawww-dataCopyright (c) 2007 Matt Aimonetti Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.googlecharts-1.6.12/README.txt0000644000004100000410000000012512564736151016020 0ustar www-datawww-dataCHECK README.markdown (open as a text file) http://github.com/mattetti/googlechartsgooglecharts-1.6.12/README0000644000004100000410000000000012564736151015172 0ustar www-datawww-datagooglecharts-1.6.12/History.txt0000644000004100000410000000376212564736151016536 0ustar www-datawww-data== 1.6.12 * added license to gemspec * added pie_c type for concentric pie charts == 1.6.10 * added support for custom position on axis with label (parameter chxp) * refactored bar chart * fixed issue #44 * allows GChart to take a theme == 1.6.8 * added title alignment support == 1.6.7 * changed url for ssl connection == 1.6.6 * added ssl support * refactored code * аdded ability to set the legend position * fixed legend position value * separated labels and legends for pies == 1.3.6 * support nil values. The Google Charts API specifies that a single underscore (_) can be used to omit a value from a line chart with 'simple' data encoding, and a double underscore (__) can do the same for a chart with 'extended' data encoding. (Matt Moyer) * allow a label to appear on a google-o-meter via the :legend option. (hallettj) == 1.3.5 * added code to properly escape image tag URLs (mokolabs) * added themes support + 4 default themes (keynote, thirty7signals, pastel, greyscale) chart.line(:theme=>:keynote) (jakehow) == 1.3.4 * updated documentation and cleaned it up (mokolabs) * added support for custom class, id and alt tags when using the image_tag format (i.e Gchart.line(:data => [0, 26], :format => 'image_tag')) (mokolabs) == 1.3.2 - 1.3.3 * changes required by github == 1.3.1 * added width and spacing options == 1.3.0 * added support for google-o-meter * fixed a bug when the max value of a data set was 0 == 1.2.0 * added support for sparklines == 1.1.0 * fixed another bug fix related to the uri escaping required to download the file properly. == 1.0.0 * fixed the (URI::InvalidURIError) issue == 0.2.0 * added export options (file and image tag) * added support for all arguments to be passed as a string or an array == 0.1.0 2007-12-11 * fixed the axis labels == 0.0.3 2007-12-11 * added :chart_background alias and fixed a bug related to the background colors. == 0.0.2 2007-12-11 * added support for more features and aliases == 0.0.1 2007-12-08 * 1 major enhancement: * Initial release googlecharts-1.6.12/spec/0000755000004100000410000000000012564736151015256 5ustar www-datawww-datagooglecharts-1.6.12/spec/gchart_spec.rb0000644000004100000410000007312712564736151020077 0ustar www-datawww-datarequire File.dirname(__FILE__) + '/spec_helper.rb' require File.dirname(__FILE__) + '/../lib/gchart' Chart::Theme.add_theme_file("#{File.dirname(__FILE__)}/fixtures/test_theme.yml") # Time to add your specs! # http://rspec.rubyforge.org/ describe "The Gchart class" do it "should show supported_types on error" do expect(Gchart.supported_types).to match(/line/) end it "should return supported types" do expect(Gchart.types).to include('line') end it "should support theme option" do chart = Gchart.new(:type => 'line',:theme => :test) expect(chart.send('url')).to include('chco=6886B4,FDD84E') end end describe "generating a default Gchart" do before(:each) do @chart = Gchart.line end it "should create a line break when a pipe character is encountered" do @chart = Gchart.line(:title => "title|subtitle") expect(@chart).to include("chtt=title\nsubtitle") end it "should include the Google URL" do expect(@chart).to include("http://chart.apis.google.com/chart?") end it "should have a default size" do expect(@chart).to include('chs=300x200') end it "should be able to have a custom size" do expect(Gchart.line(:size => '400x600')).to include('chs=400x600') expect(Gchart.line(:width => 400, :height => 600)).to include('chs=400x600') end it "should have query parameters in predictable order" do expect(Gchart.line(:axis_with_labels => 'x,y,r', :size => '400x600')).to match(/chxt=.+cht=.+chs=/) end it "should have a type" do expect(@chart).to include('cht=lc') end it 'should use theme defaults if theme is set' do expect(Gchart.line(:theme=>:test)).to include('chco=6886B4,FDD84E') expect(Gchart.line(:theme=>:test)).to match(/chf=(c,s,FFFFFF\|bg,s,FFFFFF|bg,s,FFFFFF\|c,s,FFFFFF)/) end it "should use the simple encoding by default with auto max value" do # 9 is the max value in simple encoding, 26 being our max value the 2nd encoded value should be 9 expect(Gchart.line(:data => [0, 26])).to include('chd=s:A9') expect(Gchart.line(:data => [0, 26], :max_value => 26, :axis_with_labels => 'y')).to include('chxr=0,0,26') end it "should support simple encoding with and without max_value" do expect(Gchart.line(:data => [0, 26], :max_value => 26)).to include('chd=s:A9') expect(Gchart.line(:data => [0, 26], :max_value => false)).to include('chd=s:Aa') end it "should support the extended encoding and encode properly" do expect(Gchart.line(:data => [0, 10], :encoding => 'extended', :max_value => false)).to include('chd=e:AA') expect(Gchart.line(:encoding => 'extended', :max_value => false, :data => [[0,25,26,51,52,61,62,63], [64,89,90,115,4084]] )).to include('chd=e:AAAZAaAzA0A9A-A.,BABZBaBz.0') end it "should auto set the max value for extended encoding" do expect(Gchart.line(:data => [0, 25], :encoding => 'extended', :max_value => false)).to include('chd=e:AAAZ') # Extended encoding max value is '..' expect(Gchart.line(:data => [0, 25], :encoding => 'extended')).to include('chd=e:AA..') end it "should be able to have data with text encoding" do expect(Gchart.line(:data => [10, 5.2, 4, 45, 78], :encoding => 'text')).to include('chd=t:10,5.2,4,45,78') end it "should be able to have missing data points with text encoding" do expect(Gchart.line(:data => [10, 5.2, nil, 45, 78], :encoding => 'text')).to include('chd=t:10,5.2,_,45,78') end it "should handle max and min values with text encoding" do expect(Gchart.line(:data => [10, 5.2, 4, 45, 78], :encoding => 'text')).to include('chds=0,78') end it "should automatically handle negative values with proper max/min limits when using text encoding" do expect(Gchart.line(:data => [-10, 5.2, 4, 45, 78], :encoding => 'text')).to include('chds=-10,78') end it "should handle negative values with manual max/min limits when using text encoding" do expect(Gchart.line(:data => [-10, 5.2, 4, 45, 78], :encoding => 'text', :min_value => -20, :max_value => 100)).to include('chds=-20,100') end it "should set the proper axis values when using text encoding and negative values" do expect(Gchart.bar( :data => [[-10], [100]], :encoding => 'text', :horizontal => true, :min_value => -20, :max_value => 100, :axis_with_labels => 'x', :bar_colors => ['FD9A3B', '4BC7DC'])).to include("chxr=0,-20,100") end it "should be able to have multiple set of data with text encoding" do expect(Gchart.line(:data => [[10, 5.2, 4, 45, 78], [20, 40, 70, 15, 99]], :encoding => 'text')).to include(Gchart.jstize('chd=t:10,5.2,4,45,78|20,40,70,15,99')) end it "should be able to receive a custom param" do expect(Gchart.line(:custom => 'ceci_est_une_pipe')).to include('ceci_est_une_pipe') end it "should be able to set label axis" do expect(Gchart.line(:axis_with_labels => 'x,y,r')).to include('chxt=x,y,r') expect(Gchart.line(:axis_with_labels => ['x','y','r'])).to include('chxt=x,y,r') end it "should be able to have axis labels" do expect(Gchart.line(:axis_labels => ['Jan|July|Jan|July|Jan', '0|100', 'A|B|C', '2005|2006|2007'])).to include(Gchart.jstize('chxl=0:|Jan|July|Jan|July|Jan|1:|0|100|2:|A|B|C|3:|2005|2006|2007')) expect(Gchart.line(:axis_labels => ['Jan|July|Jan|July|Jan'])).to include(Gchart.jstize('chxl=0:|Jan|July|Jan|July|Jan')) expect(Gchart.line(:axis_labels => [['Jan','July','Jan','July','Jan']])).to include(Gchart.jstize('chxl=0:|Jan|July|Jan|July|Jan')) expect(Gchart.line(:axis_labels => [['Jan','July','Jan','July','Jan'], ['0','100'], ['A','B','C'], ['2005','2006','2007']])).to include(Gchart.jstize('chxl=0:|Jan|July|Jan|July|Jan|1:|0|100|2:|A|B|C|3:|2005|2006|2007')) end def labeled_line(options = {}) Gchart.line({:data => @data, :axis_with_labels => 'x,y'}.merge(options)) end it "should display ranges properly" do @data = [85,107,123,131,155,172,173,189,203,222,217,233,250,239,256,267,247,261,275,295,288,305,322,307,325,347,331,346,363,382,343,359,383,352,374,393,358,379,396,416,377,398,419,380,409,426,453,432,452,465,436,460,480,440,457,474,501,457,489,507,347,373,413,402,424,448,475,488,513,475,507,530,440,476,500,518,481,512,531,367,396,423,387,415,446,478,442,469,492,463,489,508,463,491,518,549,503,526,547,493,530,549,493,520,541,564,510,535,564,492,512,537,502,530,548,491,514,538,568,524,548,568,512,533,552,577,520,545,570,516,536,555,514,536,566,521,553,579,604,541,569,595,551,581,602,549,576,606,631,589,615,650,597,624,646,672,605,626,654,584,608,631,574,597,622,559,591,614,644,580,603,629,584,615,631,558,591,618,641,314,356,395,397,429,450,421,454,477,507,458,490,560,593] expect(labeled_line(:axis_labels => [((1..24).to_a << 1)])). to include('chxr=0,85,672') end def labeled_bar(options = {}) Gchart.bar({:data => @data, :axis_with_labels => 'x,y', :axis_labels => [(1..12).to_a], :encoding => "text" }.merge(options)) end it "should force the y range properly" do @data = [1,1,1,1,1,1,1,1,6,2,1,1] expect(labeled_bar( :axis_range => [[0,0],[0,16]] )).to include('chxr=0,0,0|1,0,16') expect(labeled_bar( :max_value => 16, :axis_range => [[0,0],[0,16]] )).to include('chxr=0,0,16|1,0,16') # nil means ignore axis expect(labeled_bar( :axis_range => [nil,[0,16]] )).to include('chxr=1,0,16') # empty array means take defaults expect(labeled_bar( :max_value => 16, :axis_range => [[],[0,16]] )).to include('chxr=0,0,16|1,0,16') expect(labeled_bar( :axis_range => [[],[0,16]] )).to include('chxr=0,0|1,0,16') expect(Gchart.line( :data => [0,20, 40, 60, 140, 230, 60], :axis_with_labels => 'y')).to include("chxr=0,0,230") end it "should take in consideration the max value when creating a range" do data = [85,107,123,131,155,172,173,189,203,222,217,233,250,239,256,267,247,261,275,295,288,305,322,307,325,347,331,346,363,382,343,359,383,352,374,393,358,379,396,416,377,398,419,380,409,426,453,432,452,465,436,460,480,440,457,474,501,457,489,507,347,373,413,402,424,448,475,488,513,475,507,530,440,476,500,518,481,512,531,367,396,423,387,415,446,478,442,469,492,463,489,508,463,491,518,549,503,526,547,493,530,549,493,520,541,564,510,535,564,492,512,537,502,530,548,491,514,538,568,524,548,568,512,533,552,577,520,545,570,516,536,555,514,536,566,521,553,579,604,541,569,595,551,581,602,549,576,606,631,589,615,650,597,624,646,672,605,626,654,584,608,631,574,597,622,559,591,614,644,580,603,629,584,615,631,558,591,618,641,314,356,395,397,429,450,421,454,477,507,458,490,560,593] url = Gchart.line(:data => data, :axis_with_labels => 'x,y', :axis_labels => [((1..24).to_a << 1)], :max_value => 700) expect(url).to include('chxr=0,85,700') end it 'should generate different labels and legend' do expect(Gchart.pie(:legend => %w(1 2 3), :labels=>%w(one two three))).to(include('chdl=1|2|3') && include('chl=one|two|three')) end end describe "generating different type of charts" do it "should be able to generate a line chart" do expect(Gchart.line).to be_an_instance_of(String) expect(Gchart.line).to include('cht=lc') end it "should be able to generate a sparkline chart" do expect(Gchart.sparkline).to be_an_instance_of(String) expect(Gchart.sparkline).to include('cht=ls') end it "should be able to generate a line xy chart" do expect(Gchart.line_xy).to be_an_instance_of(String) expect(Gchart.line_xy).to include('cht=lxy') end it "should be able to generate a scatter chart" do expect(Gchart.scatter).to be_an_instance_of(String) expect(Gchart.scatter).to include('cht=s') end it "should be able to generate a bar chart" do expect(Gchart.bar).to be_an_instance_of(String) expect(Gchart.bar).to include('cht=bvs') end it "should be able to generate a Venn diagram" do expect(Gchart.venn).to be_an_instance_of(String) expect(Gchart.venn).to include('cht=v') end it "should be able to generate a Pie Chart" do expect(Gchart.pie).to be_an_instance_of(String) expect(Gchart.pie).to include('cht=p') end it "should be able to generate a Concentric Pie Chart" do expect(Gchart.pie_c).to be_an_instance_of(String) expect(Gchart.pie_c).to include('cht=pc') expect(Gchart.pie_c(size: '240x240', data: [[-1], [2,3]])).to include('-1|1,2,3') end it "should be able to generate a Google-O-Meter" do expect(Gchart.meter).to be_an_instance_of(String) expect(Gchart.meter).to include('cht=gom') end it "should be able to generate a map chart" do expect(Gchart.map).to be_an_instance_of(String) expect(Gchart.map).to include('cht=t') end it "should not support other types" do msg = "sexy is not a supported chart format. Please use one of the following: #{Gchart.supported_types}." expect{Gchart.sexy}.to raise_error(NoMethodError) end end describe "range markers" do it "should be able to generate given a hash of range-marker options" do expect(Gchart.line(:range_markers => {:start_position => 0.59, :stop_position => 0.61, :color => 'ff0000'})).to include('chm=r,ff0000,0,0.59,0.61') end it "should be able to generate given an array of range-marker hash options" do expect(Gchart.line(:range_markers => [ {:start_position => 0.59, :stop_position => 0.61, :color => 'ff0000'}, {:start_position => 0, :stop_position => 0.6, :color => '666666'}, {:color => 'cccccc', :start_position => 0.6, :stop_position => 1} ])).to include(Gchart.jstize('r,ff0000,0,0.59,0.61|r,666666,0,0,0.6|r,cccccc,0,0.6,1')) end it "should allow a :overlaid? to be set" do expect(Gchart.line(:range_markers => {:start_position => 0.59, :stop_position => 0.61, :color => 'ffffff', :overlaid? => true})).to include('chm=r,ffffff,0,0.59,0.61,1') expect(Gchart.line(:range_markers => {:start_position => 0.59, :stop_position => 0.61, :color => 'ffffff', :overlaid? => false})).to include('chm=r,ffffff,0,0.59,0.61') end describe "when setting the orientation option" do before(:each) do @options = {:start_position => 0.59, :stop_position => 0.61, :color => 'ff0000'} end it "to vertical (R) if given a valid option" do expect(Gchart.line(:range_markers => @options.merge(:orientation => 'v'))).to include('chm=R') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'V'))).to include('chm=R') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'R'))).to include('chm=R') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'vertical'))).to include('chm=R') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'Vertical'))).to include('chm=R') end it "to horizontal (r) if given a valid option (actually anything other than the vertical options)" do expect(Gchart.line(:range_markers => @options.merge(:orientation => 'horizontal'))).to include('chm=r') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'h'))).to include('chm=r') expect(Gchart.line(:range_markers => @options.merge(:orientation => 'etc'))).to include('chm=r') end it "if left blank defaults to horizontal (r)" do expect(Gchart.line(:range_markers => @options)).to include('chm=r') end end end describe "a bar graph" do it "should have a default vertical orientation" do expect(Gchart.bar).to include('cht=bvs') end it "should be able to have a different orientation" do expect(Gchart.bar(:orientation => 'vertical')).to include('cht=bvs') expect(Gchart.bar(:orientation => 'v')).to include('cht=bvs') expect(Gchart.bar(:orientation => 'h')).to include('cht=bhs') expect(Gchart.bar(:orientation => 'horizontal')).to include('cht=bhs') expect(Gchart.bar(:horizontal => false)).to include('cht=bvs') end it "should be set to be stacked by default" do expect(Gchart.bar).to include('cht=bvs') end it "should be able to stacked, grouped or overlapped" do expect(Gchart.bar(:stacked => true)).to include('cht=bvs') expect(Gchart.bar(:stacked => false)).to include('cht=bvs') expect(Gchart.bar(:grouped => true)).to include('cht=bvg') expect(Gchart.bar(:grouped => false)).to include('cht=bvs') expect(Gchart.bar(:overlapped => true)).to include('cht=bvo') expect(Gchart.bar(:overlapped => false)).to include('cht=bvs') end it "should be able to have different bar colors" do expect(Gchart.bar(:bar_colors => 'efefef,00ffff')).to include('chco=') expect(Gchart.bar(:bar_colors => 'efefef,00ffff')).to include('chco=efefef,00ffff') # alias expect(Gchart.bar(:bar_color => 'efefef')).to include('chco=efefef') end it "should be able to have different bar colors when using an array of colors" do expect(Gchart.bar(:bar_colors => ['efefef','00ffff'])).to include('chco=efefef,00ffff') end it 'should be able to accept a string of width and spacing options' do expect(Gchart.bar(:bar_width_and_spacing => '25,6')).to include('chbh=25,6') end it 'should be able to accept a single fixnum width and spacing option to set the bar width' do expect(Gchart.bar(:bar_width_and_spacing => 25)).to include('chbh=25') end it 'should be able to accept an array of width and spacing options' do expect(Gchart.bar(:bar_width_and_spacing => [25,6,12])).to include('chbh=25,6,12') expect(Gchart.bar(:bar_width_and_spacing => [25,6])).to include('chbh=25,6') expect(Gchart.bar(:bar_width_and_spacing => [25])).to include('chbh=25') end describe "with a hash of width and spacing options" do before(:each) do @default_width = 23 @default_spacing = 4 @default_group_spacing = 8 end it 'should be able to have a custom bar width' do expect(Gchart.bar(:bar_width_and_spacing => {:width => 19})).to include("chbh=19,#{@default_spacing},#{@default_group_spacing}") end it 'should be able to have custom spacing' do expect(Gchart.bar(:bar_width_and_spacing => {:spacing => 19})).to include("chbh=#{@default_width},19,#{@default_group_spacing}") end it 'should be able to have custom group spacing' do expect(Gchart.bar(:bar_width_and_spacing => {:group_spacing => 19})).to include("chbh=#{@default_width},#{@default_spacing},19") end end end describe "a radar chart" do before(:each) do @chart = Gchart.radar(:title => 'Chart Title') end it "should be able have a chart title" do expect(@chart).to include("chtt=Chart+Title") end it "should allow axis labels positions to be used" do expect(Gchart.radar(:custom_axis_with_labels => '0,0,50,100')).to include('chxp=0,0,50,100') end it "should allow array of axis labels positions to be used " do expect(Gchart.radar(:custom_axis_with_labels => ['0', '0', '50', '100'])).to include('chxp=0,0,50,100') end end describe "a line chart" do before(:each) do @title = 'Chart Title' @legend = ['first data set label', 'n data set label'] @chart = Gchart.line(:title => @title, :legend => @legend) end it 'should be able have a chart title' do expect(@chart).to include("chtt=Chart+Title") end it "should be able to a custom color, size and alignment for title" do expect(Gchart.line(:title => @title, :title_color => 'FF0000')).to include('chts=FF0000') expect(Gchart.line(:title => @title, :title_size => '20')).to include('chts=454545,20') expect(Gchart.line(:title => @title, :title_size => '20', :title_alignment => :left)).to include('chts=454545,20,l') end it "should be able to have multiple legends" do expect(@chart).to include(Gchart.jstize("chdl=first+data+set+label|n+data+set+label")) end it "should escape text values in url" do title = 'Chart & Title' legend = ['first data & set label', 'n data set label'] chart = Gchart.line(:title => title, :legend => legend) expect(chart).to include(Gchart.jstize("chdl=first+data+%26+set+label|n+data+set+label")) end it "should be able to have one legend" do chart = Gchart.line(:legend => 'legend label') expect(chart).to include("chdl=legend+label") end it "should be able to set the position of the legend" do title = 'Chart & Title' legend = ['first data & set label', 'n data set label'] chart = Gchart.line(:title => title, :legend => legend, :legend_position => :bottom_vertical) expect(chart).to include("chdlp=bv") chart = Gchart.line(:title => title, :legend => legend, :legend_position => 'r') expect(chart).to include("chdlp=r") end it "should be able to set the background fill" do expect(Gchart.line(:bg => 'efefef')).to include("chf=bg,s,efefef") expect(Gchart.line(:bg => {:color => 'efefef', :type => 'solid'})).to include("chf=bg,s,efefef") expect(Gchart.line(:bg => {:color => 'efefef', :type => 'gradient'})).to include("chf=bg,lg,0,efefef,0,ffffff,1") expect(Gchart.line(:bg => {:color => 'efefef,0,ffffff,1', :type => 'gradient'})).to include("chf=bg,lg,0,efefef,0,ffffff,1") expect(Gchart.line(:bg => {:color => 'efefef', :type => 'gradient', :angle => 90})).to include("chf=bg,lg,90,efefef,0,ffffff,1") expect(Gchart.line(:bg => {:color => 'efefef', :type => 'stripes'})).to include("chf=bg,ls,90,efefef,0.2,ffffff,0.2") end it "should be able to set a graph fill" do expect(Gchart.line(:graph_bg => 'efefef')).to include("chf=c,s,efefef") expect(Gchart.line(:graph_bg => {:color => 'efefef', :type => 'solid'})).to include("chf=c,s,efefef") expect(Gchart.line(:graph_bg => {:color => 'efefef', :type => 'gradient'})).to include("chf=c,lg,0,efefef,0,ffffff,1") expect(Gchart.line(:graph_bg => {:color => 'efefef,0,ffffff,1', :type => 'gradient'})).to include("chf=c,lg,0,efefef,0,ffffff,1") expect(Gchart.line(:graph_bg => {:color => 'efefef', :type => 'gradient', :angle => 90})).to include("chf=c,lg,90,efefef,0,ffffff,1") end it "should be able to set both a graph and a background fill" do expect(Gchart.line(:bg => 'efefef', :graph_bg => '76A4FB')).to match /chf=(bg,s,efefef\|c,s,76A4FB|c,s,76A4FB\|bg,s,efefef)/ end it "should be able to have different line colors" do expect(Gchart.line(:line_colors => 'efefef|00ffff')).to include(Gchart.jstize('chco=efefef|00ffff')) expect(Gchart.line(:line_color => 'efefef|00ffff')).to include(Gchart.jstize('chco=efefef|00ffff')) end it "should be able to render a graph where all the data values are 0" do expect(Gchart.line(:data => [0, 0, 0])).to include("chd=s:AAA") end end describe "a sparkline chart" do before(:each) do @title = 'Chart Title' @legend = ['first data set label', 'n data set label'] @jstized_legend = Gchart.jstize(@legend.join('|')) @data = [27,25,25,25,25,27,100,31,25,36,25,25,39,25,31,25,25,25,26,26,25,25,28,25,25,100,28,27,31,25,27,27,29,25,27,26,26,25,26,26,35,33,34,25,26,25,36,25,26,37,33,33,37,37,39,25,25,25,25] @chart = Gchart.sparkline(:title => @title, :data => @data, :legend => @legend) end it "should create a sparkline" do expect(@chart).to include('cht=ls') end it 'should be able have a chart title' do expect(@chart).to include("chtt=Chart+Title") end it "should be able to a custom color and size title" do expect(Gchart.sparkline(:title => @title, :title_color => 'FF0000')).to include('chts=FF0000') expect(Gchart.sparkline(:title => @title, :title_size => '20')).to include('chts=454545,20') end it "should be able to have multiple legends" do expect(@chart).to include(Gchart.jstize("chdl=first+data+set+label|n+data+set+label")) end it "should be able to have one legend" do chart = Gchart.sparkline(:legend => 'legend label') expect(chart).to include("chdl=legend+label") end it "should be able to set the background fill" do expect(Gchart.sparkline(:bg => 'efefef')).to include("chf=bg,s,efefef") expect(Gchart.sparkline(:bg => {:color => 'efefef', :type => 'solid'})).to include("chf=bg,s,efefef") expect(Gchart.sparkline(:bg => {:color => 'efefef', :type => 'gradient'})).to include("chf=bg,lg,0,efefef,0,ffffff,1") expect(Gchart.sparkline(:bg => {:color => 'efefef,0,ffffff,1', :type => 'gradient'})).to include("chf=bg,lg,0,efefef,0,ffffff,1") expect(Gchart.sparkline(:bg => {:color => 'efefef', :type => 'gradient', :angle => 90})).to include("chf=bg,lg,90,efefef,0,ffffff,1") expect(Gchart.sparkline(:bg => {:color => 'efefef', :type => 'stripes'})).to include("chf=bg,ls,90,efefef,0.2,ffffff,0.2") end it "should be able to set a graph fill" do expect(Gchart.sparkline(:graph_bg => 'efefef')).to include("chf=c,s,efefef") expect(Gchart.sparkline(:graph_bg => {:color => 'efefef', :type => 'solid'})).to include("chf=c,s,efefef") expect(Gchart.sparkline(:graph_bg => {:color => 'efefef', :type => 'gradient'})).to include("chf=c,lg,0,efefef,0,ffffff,1") expect(Gchart.sparkline(:graph_bg => {:color => 'efefef,0,ffffff,1', :type => 'gradient'})).to include("chf=c,lg,0,efefef,0,ffffff,1") expect(Gchart.sparkline(:graph_bg => {:color => 'efefef', :type => 'gradient', :angle => 90})).to include("chf=c,lg,90,efefef,0,ffffff,1") end it "should be able to set both a graph and a background fill" do expect(Gchart.sparkline(:bg => 'efefef', :graph_bg => '76A4FB')).to match(/chf=(bg,s,efefef\|c,s,76A4FB|c,s,76A4FB\|bg,s,efefef)/) end it "should be able to have different line colors" do expect(Gchart.sparkline(:line_colors => 'efefef|00ffff')).to include(Gchart.jstize('chco=efefef|00ffff')) expect(Gchart.sparkline(:line_color => 'efefef|00ffff')).to include(Gchart.jstize('chco=efefef|00ffff')) end end describe "a 3d pie chart" do before(:each) do @title = 'Chart Title' @legend = ['first data set label', 'n data set label'] @jstized_legend = Gchart.jstize(@legend.join('|')) @data = [12,8,40,15,5] @chart = Gchart.pie(:title => @title, :legend => @legend, :data => @data) end it "should create a pie" do expect(@chart).to include('cht=p') end it "should be able to be in 3d" do expect(Gchart.pie_3d(:title => @title, :legend => @legend, :data => @data)).to include('cht=p3') end end describe "a google-o-meter" do before(:each) do @data = [70] @legend = ['arrow points here'] @jstized_legend = Gchart.jstize(@legend.join('|')) @chart = Gchart.meter(:data => @data) end it "should create a meter" do expect(@chart).to include('cht=gom') end it "should be able to set a solid background fill" do expect(Gchart.meter(:bg => 'efefef')).to include("chf=bg,s,efefef") expect(Gchart.meter(:bg => {:color => 'efefef', :type => 'solid'})).to include("chf=bg,s,efefef") end it "should be able to set labels by using the legend or labesl accessor" do expect(Gchart.meter(:title => @title, :labels => @legend, :data => @data)).to include("chl=#{@jstized_legend}") expect(Gchart.meter(:title => @title, :labels => @legend, :data => @data)).to eq(Gchart.meter(:title => @title, :legend => @legend, :data => @data)) end end describe "a map chart" do before(:each) do @data = [0,100,50,32] @geographical_area = 'usa' @map_colors = ['FFFFFF', 'FF0000', 'FFFF00', '00FF00'] @country_codes = ['MT', 'WY', "ID", 'SD'] @chart = Gchart.map(:data => @data, :encoding => 'text', :size => '400x300', :geographical_area => @geographical_area, :map_colors => @map_colors, :country_codes => @country_codes) end it "should create a map" do expect(@chart).to include('cht=t') end it "should set the geographical area" do expect(@chart).to include('chtm=usa') end it "should set the map colors" do expect(@chart).to include('chco=FFFFFF,FF0000,FFFF00,00FF00') end it "should set the country/state codes" do expect(@chart).to include('chld=MTWYIDSD') end it "should set the chart data" do expect(@chart).to include('chd=t:0,100,50,32') end end describe 'exporting a chart' do it "should be available in the url format by default" do expect(Gchart.line(:data => [0, 26], :format => 'url')).to eq(Gchart.line(:data => [0, 26])) end it "should be available as an image tag" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag')).to match(/Google Chart/) end it "should be available as an image tag using img_tag alias" do expect(Gchart.line(:data => [0, 26], :format => 'img_tag')).to match(/Google Chart/) end it "should be available as an image tag using custom dimensions" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :size => '400x400')).to match(/Google Chart/) end it "should be available as an image tag using custom alt text" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :alt => 'Sexy chart')).to match(/Sexy chart/) end it "should be available as an image tag using custom title text" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :title => 'Sexy chart')).to match(/Google Chart/) end it "should be available as an image tag using custom css id selector" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :id => 'chart')).to match(/Google Chart/) end it "should be available as an image tag using custom css class selector" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :class => 'chart')).to match(/Google Chart/) end it "should use ampersands to separate key/value pairs in URLs by default" do expect(Gchart.line(:data => [0, 26])).to include "&" expect(Gchart.line(:data => [0, 26])).not_to include "&" end it "should escape ampersands in URLs when used as an image tag" do expect(Gchart.line(:data => [0, 26], :format => 'image_tag', :class => 'chart')).to satisfy {|chart| expect(chart).to include "&" } end it "should be available as a file" do File.delete('chart.png') if File.exist?('chart.png') Gchart.line(:data => [0, 26], :format => 'file') expect(File.exist?('chart.png')).to be File.delete('chart.png') if File.exist?('chart.png') end it "should be available as a file using a custom file name" do File.delete('custom_file_name.png') if File.exist?('custom_file_name.png') Gchart.line(:data => [0, 26], :format => 'file', :filename => 'custom_file_name.png') expect(File.exist?('custom_file_name.png')).to be File.delete('custom_file_name.png') if File.exist?('custom_file_name.png') end it "should work even with multiple attrs" do File.delete('foo.png') if File.exist?('foo.png') Gchart.line(:size => '400x200', :data => [1,2,3,4,5], # :axis_labels => [[1,2,3,4, 5], %w[foo bar]], :axis_with_labels => 'x,r', :format => "file", :filename => "foo.png" ) expect(File.exist?('foo.png')).to be File.delete('foo.png') if File.exist?('foo.png') end end describe 'SSL support' do it 'should change url if is presented' do expect(Gchart.line(:use_ssl => true)).to include('https://chart.googleapis.com/chart?') end it "should be available as a file" do pending "unexpected error under Travis CI (should be fixed using http://martinottenwaelter.fr/2010/12/ruby19-and-the-ssl-error/)" File.delete('chart.png') if File.exist?('chart.png') Gchart.line(:data => [0, 26], :format => 'file', :use_ssl => true) expect(File.exist?('chart.png')).to be_true File.delete('chart.png') if File.exist?('chart.png') end end googlecharts-1.6.12/spec/spec_helper.rb0000644000004100000410000000014212564736151020071 0ustar www-datawww-databegin require 'rspec' rescue LoadError require 'rubygems' gem 'rspec' require 'rspec' end googlecharts-1.6.12/spec/fixtures/0000755000004100000410000000000012564736151017127 5ustar www-datawww-datagooglecharts-1.6.12/spec/fixtures/test_theme.yml0000644000004100000410000000024112564736151022010 0ustar www-datawww-data:test: :colors: - &blue 6886B4 - &yellow FDD84E - &white FFFFFF :bar_colors: [ *blue, *yellow ] :background: *white :chart_background: *whitegooglecharts-1.6.12/spec/fixtures/another_test_theme.yml0000644000004100000410000000024312564736151023532 0ustar www-datawww-data:test_two: :colors: - &blue 6886B4 - &yellow FDD84E - &grey 333333 :bar_colors: [ *blue, *yellow ] :background: *grey :chart_background: *grey googlecharts-1.6.12/spec/theme_spec.rb0000644000004100000410000000265212564736151017724 0ustar www-datawww-datarequire File.dirname(__FILE__) + '/spec_helper.rb' require File.dirname(__FILE__) + '/../lib/gchart' describe "generating a default Gchart" do it 'should be able to add additional theme files' do expect(Chart::Theme.theme_files).not_to include("#{File.dirname(__FILE__)}/fixtures/another_test_theme.yml") Chart::Theme.add_theme_file("#{File.dirname(__FILE__)}/fixtures/another_test_theme.yml") expect(Chart::Theme.theme_files).to include("#{File.dirname(__FILE__)}/fixtures/another_test_theme.yml") end it 'should be able to load themes from the additional theme files' do expect { Chart::Theme.load(:test_two) }.not_to raise_error end it 'should raise ThemeNotFound if theme does not exist' do expect { Chart::Theme.load(:nonexistent) }.to raise_error(Chart::Theme::ThemeNotFound, "Could not locate the nonexistent theme ...") end it 'should set colors array' do expect(Chart::Theme.load(:keynote).colors).to eql(["6886B4", "FDD84E", "72AE6E", "D1695E", "8A6EAF", "EFAA43", "FFFFFF", "000000"]) end it 'should set bar colors array' do expect(Chart::Theme.load(:keynote).bar_colors).to eql(["6886B4", "FDD84E", "72AE6E", "D1695E", "8A6EAF", "EFAA43"]) end it 'should set background' do expect(Chart::Theme.load(:keynote).background).to eql("000000") end it 'should set chart background' do expect(Chart::Theme.load(:keynote).chart_background).to eql("FFFFFF") end endgooglecharts-1.6.12/.travis.yml0000644000004100000410000000011612564736151016433 0ustar www-datawww-datalanguage: ruby rvm: - 1.8.7 - ree - 1.9.2 - 1.9.3 - 2.0.0 - jruby googlecharts-1.6.12/lib/0000755000004100000410000000000012564736151015072 5ustar www-datawww-datagooglecharts-1.6.12/lib/gchart.rb0000644000004100000410000005037112564736151016675 0ustar www-datawww-data$:.unshift File.dirname(__FILE__) require 'gchart/version' require 'gchart/theme' require "net/http" require "net/https" require "uri" require "cgi" require 'enumerator' class Gchart include GchartInfo def self.url(use_ssl = false) if use_ssl 'https://chart.googleapis.com/chart?' else 'http://chart.apis.google.com/chart?' end end def self.types @types ||= ['line', 'line_xy', 'scatter', 'bar', 'venn', 'pie', 'pie_3d', 'pie_c', 'jstize', 'sparkline', 'meter', 'map', 'radar'] end def self.simple_chars @simple_chars ||= ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a end def self.chars @chars ||= simple_chars + ['-', '.'] end def self.ext_pairs @ext_pairs ||= chars.map { |char_1| chars.map { |char_2| char_1 + char_2 } }.flatten end def self.default_filename 'chart.png' end attr_accessor :title, :type, :width, :height, :curved, :horizontal, :grouped, :overlapped, :legend, :legend_position, :labels, :data, :encoding, :bar_colors, :title_color, :title_size, :title_alignment, :custom, :axis_with_labels, :custom_axis_with_labels, :axis_labels, :bar_width_and_spacing, :id, :alt, :klass, :range_markers, :geographical_area, :map_colors, :country_codes, :axis_range, :filename, :min, :max, :colors, :usemap attr_accessor :bg_type, :bg_color, :bg_angle, :chart_type, :chart_color, :chart_angle, :axis_range, :thickness, :new_markers, :grid_lines, :use_ssl attr_accessor :min_value, :max_value types.each do |type| instance_eval <<-DYNCLASSMETH def #{type}(options = {}) # Start with theme defaults if a theme is set theme = options[:theme] options = theme ? Chart::Theme.load(theme).to_options.merge(options) : options # # Extract the format and optional filename, then clean the hash format = options[:format] || 'url' options[:filename] ||= default_filename options.delete(:format) #update map_colors to become bar_colors options.update(:bar_colors => options[:map_colors]) if options.has_key?(:map_colors) chart = new(options.merge!({:type => "#{type}"})) chart.send(format) end DYNCLASSMETH end def self.version VERSION::STRING end def self.method_missing(m, options={}) raise NoMethodError, "#{m} is not a supported chart format. Please use one of the following: #{supported_types}." end def initialize(options={}) # Allow Gchart to take a theme too @theme = options[:theme] options = @theme ? Chart::Theme.load(@theme).to_options.merge(options) : options options.delete(:theme) @type = options[:type] || 'line' @data = [] @width = 300 @height = 200 @curved = false @horizontal = false @grouped = false @overlapped = false @use_ssl = false @encoding = 'simple' # @max_value = 'auto' # @min_value defaults to nil meaning zero @filename = options[:filename] # Sets the alt tag when chart is exported as image tag @alt = 'Google Chart' # Sets the CSS id selector when chart is exported as image tag @id = false # Sets the CSS class selector when chart is exported as image tag @klass = options[:class] || false # set the options value if definable options.each do |attribute, value| send("#{attribute}=", value) if self.respond_to?("#{attribute}=") end end def self.supported_types self.types.join(' ') end # Defines the Graph size using the following format: # width X height def size=(size='300x200') @width, @height = size.split("x").map { |dimension| dimension.to_i } end def size "#{width}x#{height}" end def dimensions # TODO: maybe others? [:line_xy, :scatter].include?(type) ? 2 : 1 end # Sets the orientation of a bar graph def orientation=(orientation='h') if orientation == 'h' || orientation == 'horizontal' self.horizontal = true elsif orientation == 'v' || orientation == 'vertical' self.horizontal = false end end def bar_presentation if @overlapped 'o' elsif @grouped 'g' else 's' end end def bg=(options) if options.is_a?(String) @bg_color = options elsif options.is_a?(Hash) @bg_color = options[:color] @bg_type = options[:type] @bg_angle = options[:angle] end end def graph_bg=(options) if options.is_a?(String) @chart_color = options elsif options.is_a?(Hash) @chart_color = options[:color] @chart_type = options[:type] @chart_angle = options[:angle] end end def max_value=(max_v) if max_v =~ /false/ @max_value = false else @max_value = max_v end end def min_value=(min_v) if min_v =~ /false/ @min_value = false else @min_value = min_v end end # returns the full data range as an array # it also sets the data range if not defined def full_data_range(ds) return if max_value == false ds.each_with_index do |mds, mds_index| mds[:min_value] ||= min_value mds[:max_value] ||= max_value if mds_index == 0 && type.to_s == 'bar' # TODO: unless you specify a zero line (using chp or chds), # the min_value of a bar chart is always 0. #mds[:min_value] ||= mds[:data].first.to_a.compact.min mds[:min_value] ||= 0 end if (mds_index == 0 && type.to_s == 'bar' && !grouped && mds[:data].first.is_a?(Array)) totals = [] mds[:data].each do |l| l.each_with_index do |v, index| next if v.nil? totals[index] ||= 0 totals[index] += v end end mds[:max_value] ||= totals.compact.max else all = mds[:data].flatten.compact # default min value should be 0 unless set to auto if mds[:min_value] == 'auto' mds[:min_value] = all.min else min = all.min mds[:min_value] ||= (min && min < 0 ? min : 0) end mds[:max_value] ||= all.max end end unless axis_range @calculated_axis_range = true @axis_range = ds.map{|mds| [mds[:min_value], mds[:max_value]]} if dimensions == 1 && (type.to_s != 'bar' || horizontal) tmp = axis_range.fetch(0, []) @axis_range[0] = axis_range.fetch(1, []) @axis_range[1] = tmp end end # return [min, max] unless (min.nil? || max.nil?) # @max = (max_value.nil? || max_value == 'auto') ? ds.compact.map{|mds| mds.compact.max}.max : max_value # # if min_value.nil? # min_ds_value = ds.compact.map{|mds| mds.compact.min}.min || 0 # @min = (min_ds_value < 0) ? min_ds_value : 0 # else # @min = min_value == 'auto' ? ds.compact.map{|mds| mds.compact.min}.min || 0 : min_value # end # @axis_range = [[min,max]] end def dataset if @dataset @dataset else @dataset = convert_dataset(data || []) full_data_range(@dataset) # unless axis_range @dataset end end # Sets of data to handle multiple sets def datasets datasets = [] dataset.each do |d| if d[:data].first.is_a?(Array) datasets += d[:data] else datasets << d[:data] end end datasets end def self.jstize(string) # See http://github.com/mattetti/googlecharts/issues#issue/27 #URI.escape( string ).gsub("%7C", "|") # See discussion: http://github.com/mattetti/googlecharts/commit/9b5cfb93aa51aae06611057668e631cd515ec4f3#comment_51347 string.gsub(' ', '+').gsub(/\[|\{|\}|\\|\^|\[|\]|\`|\]/) {|c| "%#{c[0].to_s.upcase}"} #string.gsub(' ', '+').gsub(/\[|\{|\}|\||\\|\^|\[|\]|\`|\]/) {|c| "%#{c[0].to_s.upcase}"} end # load all the custom aliases require 'gchart/aliases' # Returns the chart's generated PNG as a blob. (borrowed from John's gchart.rubyforge.org) def fetch url = URI.parse(self.class.url(use_ssl)) req = Net::HTTP::Post.new(url.path) req.body = query_builder req.content_type = 'application/x-www-form-urlencoded' http = Net::HTTP.new(url.host, url.port) http.verify_mode = OpenSSL::SSL::VERIFY_PEER if use_ssl http.use_ssl = use_ssl http.start {|resp| resp.request(req) }.body end # Writes the chart's generated PNG to a file. (borrowed from John's gchart.rubyforge.org) def write io_or_file = filename || self.class.default_filename return io_or_file.write(fetch) if io_or_file.respond_to?(:write) open(io_or_file, "wb+") { |io| io.write(fetch) } end # Format def image_tag image = ", # , # def set_bar_width_and_spacing width_and_spacing_values = case bar_width_and_spacing when String bar_width_and_spacing when Array bar_width_and_spacing.join(',') when Hash width = bar_width_and_spacing[:width] || 23 spacing = bar_width_and_spacing[:spacing] || 4 group_spacing = bar_width_and_spacing[:group_spacing] || 8 [width,spacing,group_spacing].join(',') else bar_width_and_spacing.to_s end "chbh=#{width_and_spacing_values}" end def set_range_markers markers = case range_markers when Hash set_range_marker(range_markers) when Array range_markers.collect{|marker| set_range_marker(marker)}.join('|') end "chm=#{markers}" end def set_range_marker(options) orientation = ['vertical', 'Vertical', 'V', 'v', 'R'].include?(options[:orientation]) ? 'R' : 'r' "#{orientation},#{options[:color]},0,#{options[:start_position]},#{options[:stop_position]}#{',1' if options[:overlaid?]}" end def fill_for(type=nil, color='', angle=nil) unless type.nil? case type when 'lg' angle ||= 0 color = "#{color},0,ffffff,1" if color.split(',').size == 1 "#{type},#{angle},#{color}" when 'ls' angle ||= 90 color = "#{color},0.2,ffffff,0.2" if color.split(',').size == 1 "#{type},#{angle},#{color}" else "#{type},#{color}" end end end # A chart can have one or many legends. # Gchart.line(:legend => 'label') # or # Gchart.line(:legend => ['first label', 'last label']) def set_legend if type.to_s =~ /meter/ @labels = legend return set_labels end if legend.is_a?(Array) "chdl=#{@legend.map{|label| "#{CGI::escape(label.to_s)}"}.join('|')}" else "chdl=#{legend}" end end def set_legend_position case @legend_position.to_s when /(bottom|b)$/ "chdlp=b" when /(bottom_vertical|bv)$/ "chdlp=bv" when /(top|t)$/ "chdlp=t" when /(top_vertical|tv)$/ "chdlp=tv" when /(right|r)$/ "chdlp=r" when /(left|l)$/ "chdlp=l" end end def set_line_thickness "chls=#{thickness}" end def set_line_markers "chm=#{new_markers}" end def set_grid_lines "chg=#{grid_lines}" end def set_labels if labels.is_a?(Array) "chl=#{@labels.map{|label| "#{CGI::escape(label.to_s)}"}.join('|')}" else "chl=#{@labels}" end end def set_axis_with_labels @axis_with_labels = axis_with_labels.join(',') if @axis_with_labels.is_a?(Array) "chxt=#{axis_with_labels}" end def set_custom_axis_with_labels @custom_axis_with_labels = custom_axis_with_labels.join(',') if @custom_axis_with_labels.is_a?(Array) "chxp=#{custom_axis_with_labels}" end def set_axis_labels if axis_labels.is_a?(Array) if RUBY_VERSION.to_f < 1.9 labels_arr = axis_labels.enum_with_index.map{|labels,index| [index,labels]} else labels_arr = axis_labels.map.with_index.map{|labels,index| [index,labels]} end elsif axis_labels.is_a?(Hash) labels_arr = axis_labels.to_a end labels_arr.map! do |index,labels| if labels.is_a?(Array) "#{index}:|#{labels.map{|label| "#{CGI::escape(label.to_s)}"}.join('|')}" else "#{index}:|#{labels}" end end "chxl=#{labels_arr.join('|')}" end # http://code.google.com/apis/chart/labels.html#axis_range # Specify a range for axis labels def set_axis_range # a passed axis_range should look like: # [[10,100]] or [[10,100,4]] or [[10,100], [20,300]] # in the second example, 4 is the interval set = @calculated_axis_range ? datasets : axis_range || datasets return unless set && set.respond_to?(:each) && set.find {|o| o}.respond_to?(:each) 'chxr=' + set.enum_for(:each_with_index).map do |axis_range, index| next nil if axis_range.nil? # ignore this axis min, max, step = axis_range if axis_range.size > 3 || step && max && step > max # this is a full series max = axis_range.compact.max step = nil end [index, (min_value || min || 0), (max_value || max), step].compact.join(',') end.compact.join("|") end def set_geographical_area "chtm=#{geographical_area}" end def set_type 'cht=' + case type.to_s when 'line' then "lc" when 'line_xy' then "lxy" when 'pie_3d' then "p3" when 'pie_c' then "pc" when 'pie' then "p" when 'venn' then "v" when 'scatter' then "s" when 'sparkline' then "ls" when 'meter' then "gom" when 'map' then "t" when 'radar' "r" + (curved? ? 's' : '') when 'bar' "b" + (horizontal? ? "h" : "v") + bar_presentation end end def fill_type(type) case type when 'solid' then 's' when 'gradient' then 'lg' when 'stripes' then 'ls' end end def number_visible n = 0 dataset.each do |mds| return n.to_s if mds[:invisible] == true if mds[:data].first.is_a?(Array) n += mds[:data].length else n += 1 end end "" end # Turns input into an array of axis hashes, dependent on the chart type def convert_dataset(ds) if dimensions == 2 # valid inputs include: # an array of >=2 arrays, or an array of >=2 hashes ds = ds.map do |d| d.is_a?(Hash) ? d : {:data => d} end elsif dimensions == 1 # valid inputs include: # a hash, an array of data, an array of >=1 array, or an array of >=1 hash if ds.is_a?(Hash) ds = [ds] elsif not ds.first.is_a?(Hash) ds = [{:data => ds}] end end ds end # just an alias def axis_set dataset end def convert_to_simple_value(number) if number.nil? "_" else value = self.class.simple_chars[number.to_i] value.nil? ? "_" : value end end def convert_to_extended_value(number) if number.nil? '__' else value = self.class.ext_pairs[number.to_i] value.nil? ? "__" : value end end def encode_scaled_dataset(chars, nil_char) dsets = [] dataset.each do |ds| if max_value != false range = ds[:max_value] - ds[:min_value] range = 1 if range == 0 end unless ds[:data].first.is_a?(Array) ldatasets = [ds[:data]] else ldatasets = ds[:data] end ldatasets.each do |l| dsets << l.map do |number| if number.nil? nil_char else unless range.nil? || range.zero? number = chars.size * (number - ds[:min_value]) / range.to_f number = [number, chars.size - 1].min end chars[number.to_i] end end.join end end dsets.join(',') end # http://code.google.com/apis/chart/#simple # Simple encoding has a resolution of 62 different values. # Allowing five pixels per data point, this is sufficient for line and bar charts up # to about 300 pixels. Simple encoding is suitable for all other types of chart regardless of size. def simple_encoding "s" + number_visible + ":" + encode_scaled_dataset(self.class.simple_chars, '_') end # http://code.google.com/apis/chart/#text # Text encoding with data scaling lets you specify arbitrary positive or # negative floating point numbers, in combination with a scaling parameter # that lets you specify a custom range for your chart. This chart is useful # when you don't want to worry about limiting your data to a specific range, # or do the calculations to scale your data down or up to fit nicely inside # a chart. # # Valid values range from (+/-)9.999e(+/-)100, and only four non-zero digits are supported (that is, 123400, 1234, 12.34, and 0.1234 are valid, but 12345, 123.45 and 123400.5 are not). # # This encoding is not available for maps. # def text_encoding chds = dataset.map{|ds| "#{ds[:min_value]},#{ds[:max_value]}" }.join(",") "t" + number_visible + ":" + datasets.map{ |ds| ds.map{|e|e||'_'}.join(',') }.join('|') + "&chds=" + chds end # http://code.google.com/apis/chart/#extended # Extended encoding has a resolution of 4,096 different values # and is best used for large charts where a large data range is required. def extended_encoding "e" + number_visible + ":" + encode_scaled_dataset(self.class.ext_pairs, '__') end def url_builder(options="") self.class.url(use_ssl) + query_builder(options) end def query_builder(options="") query_params = instance_variables.sort.map do |var| case var.to_s when '@data' set_data unless data == [] # Set the graph size when '@width' set_size unless width.nil? || height.nil? when '@type' set_type when '@title' set_title unless title.nil? when '@legend' set_legend unless legend.nil? when '@labels' set_labels unless labels.nil? when '@legend_position' set_legend_position unless legend_position.nil? when '@thickness' set_line_thickness when '@new_markers' set_line_markers when '@bg_color' set_colors when '@chart_color' set_colors if bg_color.nil? when '@bar_colors' set_bar_colors when '@bar_width_and_spacing' set_bar_width_and_spacing when '@axis_with_labels' set_axis_with_labels when '@axis_labels' set_axis_labels when '@range_markers' set_range_markers when '@grid_lines' set_grid_lines when '@custom_axis_with_labels' set_custom_axis_with_labels when '@geographical_area' set_geographical_area when '@country_codes' set_country_codes when '@custom' custom end end.compact query_params << set_axis_range # Use ampersand as default delimiter unless options == :html delimiter = '&' # Escape ampersand for html image tags else delimiter = '&' end jstize(query_params.join(delimiter)) end end googlecharts-1.6.12/lib/themes.yml0000644000004100000410000000205712564736151017106 0ustar www-datawww-data#Default themes ganked from Gruff: http://github.com/topfunky/gruff/tree/master :keynote: :colors: - &blue 6886B4 - &yellow FDD84E - &green 72AE6E - &red D1695E - &purple 8A6EAF - &orange EFAA43 - &white FFFFFF - &black !str 000000 :bar_colors: [ *blue, *yellow, *green, *red, *purple, *orange ] :background: *black :chart_background: *white :thirty7signals: :colors: - &green 339933 - &purple cc99cc - &blue 336699 - &yellow FFF804 - &red ff0000 - &orange cf5910 :bar_colors: [ *yellow, *blue, *green, *red, *purple, *orange ] :background: *white :pastel: :colors: - &blue a9dada - &green aedaa9 - &peach daaea9 - &yellow dadaa9 - &dk_purple a9a9da - &purple daaeda - &grey dadada :bar_colors: [ *blue, *green, *peach, *yellow, *dk_purple ] :background_color: *white :greyscale: :bar_colors: [ 282828, 383838, 686868, 989898, c8c8c8, e8e8e8 ] :background_color: *whitegooglecharts-1.6.12/lib/googlecharts.rb0000644000004100000410000000012112564736151020072 0ustar www-datawww-datarequire 'gchart' Googlecharts = Gchart unless Object.const_defined? 'Googlechart'googlecharts-1.6.12/lib/gchart/0000755000004100000410000000000012564736151016342 5ustar www-datawww-datagooglecharts-1.6.12/lib/gchart/theme.rb0000644000004100000410000000223712564736151017775 0ustar www-datawww-datarequire 'yaml' module Chart class Theme class ThemeNotFound < RuntimeError; end @@theme_files = ["#{File.dirname(__FILE__)}/../themes.yml"] attr_accessor :colors attr_accessor :bar_colors attr_accessor :background attr_accessor :chart_background def self.load(theme_name) theme = new(theme_name) end def self.theme_files @@theme_files end # Allows you to specify paths for custom theme files in YAML format def self.add_theme_file(file) @@theme_files << file end def initialize(theme_name) themes = {} @@theme_files.each {|f| themes.update YAML::load(File.open(f))} theme = themes[theme_name] if theme self.colors = theme[:colors] self.bar_colors = theme[:bar_colors] self.background = theme[:background] self.chart_background = theme[:chart_background] self else raise(ThemeNotFound, "Could not locate the #{theme_name} theme ...") end end def to_options {:background => background, :chart_background => chart_background, :bar_colors => bar_colors.join(',')} end end endgooglecharts-1.6.12/lib/gchart/aliases.rb0000644000004100000410000000065012564736151020311 0ustar www-datawww-dataclass Gchart alias_method :background=, :bg= alias_method :chart_bg=, :graph_bg= alias_method :chart_color=, :graph_bg= alias_method :chart_background=, :graph_bg= alias_method :bar_color=, :bar_colors= alias_method :line_colors=, :bar_colors= alias_method :line_color=, :bar_colors= alias_method :slice_colors=, :bar_colors= alias_method :horizontal?, :horizontal alias_method :curved?, :curved end googlecharts-1.6.12/lib/gchart/version.rb0000644000004100000410000000006412564736151020354 0ustar www-datawww-datamodule GchartInfo #:nodoc: VERSION = "1.6.12" end googlecharts-1.6.12/README.markdown0000644000004100000410000002543512564736151017036 0ustar www-datawww-data## Googlecharts [![Build Status](https://travis-ci.org/mattetti/googlecharts.png?branch=master)](https://travis-ci.org/mattetti/googlecharts) The goal of this Gem is to make the creation of Google Charts a simple and easy task. require 'googlecharts' Gchart.line( :size => '200x300', :title => "example title", :bg => 'efefef', :legend => ['first data set label', 'second data set label'], :data => [10, 30, 120, 45, 72]) Check out the [full documentation over there](http://googlecharts.rubyforge.org/) This gem is fully tested using Rspec, check the rspec folder for more examples. See at the bottom of this file who reported using this gem. Chart Type ------------- This gem supports the following types of charts: * line, * line_xy * sparkline * scatter * bar * venn * pie * pie_3d * google meter Googlecharts also supports graphical themes and you can easily load your own. To create a chart, simply require Gchart and call any of the existing type: require 'gchart' Gchart.pie Chart Title ------------- To add a title to a chart pass the title to your chart: Gchart.line(:title => 'Sexy Charts!') You can also specify the color and/or size Gchart.line(:title => 'Sexy Charts!', :title_color => 'FF0000', :title_size => '20') Colors ------------- Specify a color with at least a 6-letter string of hexadecimal values in the format RRGGBB. For example: * FF0000 = red * 00FF00 = green * 0000FF = blue * 000000 = black * FFFFFF = white You can optionally specify transparency by appending a value between 00 and FF where 00 is completely transparent and FF completely opaque. For example: * 0000FFFF = solid blue * 0000FF00 = transparent blue If you need to use multiple colors, check the doc. Usually you just need to pass :attribute => 'FF0000,00FF00' Some charts have more options than other, make sure to refer to the documentation. Background options: ------------- If you don't set the background option, your graph will be transparent. * You have 3 types of background http://code.google.com/apis/chart/#chart_or_background_fill - solid - gradient - stripes By default, if you set a background color, the fill will be solid: Gchart.bar(:bg => 'efefef') However you can specify another fill type such as: Gchart.line(:bg => {:color => 'efefef', :type => 'gradient'}) In the above code, we decided to have a gradient background, however since we only passed one color, the chart will start by the specified color and transition to white. By the default, the gradient angle is 0. Change it as follows: Gchart.line(:title =>'bg example', :bg => {:color => 'efefef', :type => 'gradient', :angle => 90}) For a more advance use of colors, refer to http://code.google.com/apis/chart/#linear_gradient Gchart.line(:bg => {:color => '76A4FB,1,ffffff,0', :type => 'gradient'}) The same way you set the background color, you can also set the graph background: Gchart.line(:graph_bg => 'cccccc') or both Gchart.line(:bg => {:color => '76A4FB,1,ffffff,0', :type => 'gradient'}, :graph_bg => 'cccccc', :title => 'Sexy Chart') Another type of fill is stripes http://code.google.com/apis/chart/#linear_stripes Gchart.line(:bg => {:color => 'efefef', :type => 'stripes'}) You can customize the amount of stripes, colors and width by changing the color value. Themes -------- Googlecharts comes with 4 themes: keynote, thirty7signals, pastel and greyscale. (ganked from [Gruff](http://github.com/topfunky/gruff/tree/master) Gchart.line( :theme => :keynote, :data => [[0,40,10,70,20],[41,10,80,50,40],[20,60,30,60,80],[5,23,35,10,56],[80,90,5,30,60]], :title => 'keynote' ) * keynote ![keynote](http://chart.apis.google.com/chart?chtt=keynote&chco=6886B4,FDD84E,72AE6E,D1695E,8A6EAF,EFAA43&chs=300x200&cht=lc&chd=s:AbGvN,bG2hb,NoUo2,DPXGl,29DUo&chf=c,s,FFFFFF|bg,s,000000) * thirty7signals ![37signals](http://chart.apis.google.com/chart?chtt=thirty7signals&chco=FFF804,336699,339933,ff0000,cc99cc,cf5910&chs=300x200&cht=lc&chd=s:AbGvN,bG2hb,NoUo2,DPXGl,29DUo&chf=bg,s,FFFFFF) * pastel ![pastel](http://chart.apis.google.com/chart?chtt=pastel&chco=a9dada,aedaa9,daaea9,dadaa9,a9a9da&chs=300x200&cht=lc&chd=s:AbGvN,bG2hb,NoUo2,DPXGl,29DUo) * greyscale ![greyscale](http://chart.apis.google.com/chart?chtt=greyscale&chco=282828,383838,686868,989898,c8c8c8,e8e8e8&chs=300x200&cht=lc&chd=s:AbGvN,bG2hb,NoUo2,DPXGl,29DUo) You can also use your own theme. Create a yml file using the same format as the themes located in lib/themes.yml Load your theme(s): Chart::Theme.add_theme_file("#{File.dirname(__FILE__)}/fixtures/another_test_theme.yml") And use the standard method signature to use your own theme: Gchart.line(:theme => :custom_theme, :data => [[0, 40, 10, 70, 20],[41, 10, 80, 50]], :title => 'greyscale') Legend & Labels ------------- You probably will want to use a legend or labels for your graph. Gchart.line(:legend => 'legend label') or Gchart.line(:legend => ['legend label 1', 'legend label 2']) Will do the trick. You can also use the labels alias (makes more sense when using the pie charts) chart = Gchart.pie(:labels => ['label 1', 'label 2']) Multiple axis labels ------------- Multiple axis labels are available for line charts, bar charts and scatter plots. * x = bottom x-axis * t = top x-axis * y = left y-axis * r = right y-axis Gchart.line(:axis_with_label => 'x,y,r,t') To add labels on these axis: Gchart.line(:axis_with_label => 'x,y,r,t', :axis_labels => ['Jan|July|Jan|July|Jan', '0|100', 'A|B|C', '2005|2006|2007']) Note that each array entry could also be an array but represent the labels for the corresponding axis. A question which comes back often is how do I only display the y axis label? Solution: Gchart.line( :data => [0,20, 40, 60, 140, 230, 60], :axis_with_labels => 'y') Custom axis ranges --------------- If you want to display a custom range for an axis, you need to set the range as described in the Google charts documentation: min, max, step: Gchart.line( :data => [17, 17, 11, 8, 2], :axis_with_labels => ['x', 'y'], :axis_labels => [['J', 'F', 'M', 'A', 'M']], :axis_range => [nil, [2,17,5]]) In this case, the custom axis range is only defined for y (second entry) with a minimum value of 2, max 17 and a step of 5. This is also valid if you want to set a x axis and automatically define the y labels. Data options ------------- Data are passed using an array or a nested array. Gchart.bar(:data => [1,2,4,67,100,41,234]) Gchart.bar(:data => [[1,2,4,67,100,41,234],[45,23,67,12,67,300, 250]]) By default, the graph is drawn with your max value representing 100% of the height or width of the graph. You can change that my passing the max value. Gchart.bar(:data => [1,2,4,67,100,41,234], :max_value => 300) Gchart.bar(:data => [1,2,4,67,100,41,234], :max_value => 'auto') or if you want to use the real values from your dataset: Gchart.bar(:data => [1,2,4,67,100,41,234], :max_value => false) You can also define a different encoding to add more granularity: Gchart.bar(:data => [1,2,4,67,100,41,234], :encoding => 'simple') Gchart.bar(:data => [1,2,4,67,100,41,234], :encoding => 'extended') Gchart.bar(:data => [1,2,4,67,100,41,234], :encoding => 'text') Pies: ------------- you have 2 type of pies: - Gchart.pie() the standard 2D pie _ Gchart.pie_3d() the fancy 3D pie To set labels, you can use one of these two options: @legend = ['Matt_fu', 'Rob_fu'] Gchart.pie_3d(:title => @title, :labels => @legend, :data => @data, :size => '400x200') Gchart.pie_3d(:title => @title, :legend => @legend, :data => @data, :size => '400x200') Bars: ------------- A bar chart can accept options to set the width of the bars, spacing between bars and spacing between bar groups. To set these, you can either provide a string, array or hash. The Google API sets these options in the order of width, spacing, and group spacing, with both spacing values being optional. So, if you provide a string or array, provide them in that order: Gchart.bar(:data => @data, :bar_width_and_spacing => '25,6') # width of 25, spacing of 6 Gchart.bar(:data => @data, :bar_width_and_spacing => '25,6,12') # width of 25, spacing of 6, group spacing of 12 Gchart.bar(:data => @data, :bar_width_and_spacing => [25,6]) # width of 25, spacing of 6 Gchart.bar(:data => @data, :bar_width_and_spacing => 25) # width of 25 The hash lets you set these values directly, with the Google default values set for any options you don't include: Gchart.bar(:data => @data, :bar_width_and_spacing => {:width => 19}) Gchart.bar(:data => @data, :bar_width_and_spacing => {:spacing => 10, :group_spacing => 12}) Radar: ------------- In a Radar graph, the x-axis is circular. The points can be connected by straight lines or curved lines. Gchart.radar(:data => @data, :curved => true) Sparklines: ------------- A sparkline chart has exactly the same parameters as a line chart. The only difference is that the axes lines are not drawn for sparklines by default. Google-o-meter ------------- A Google-o-meter has a few restrictions. It may only use a solid filled background and it may only have one label. Record Chart PNG file in filesystem Sample : -------------------------------------------- Multi Lines Chart Sample : chart = Gchart.new( :type => 'line', :title => "example title", :theme => :keynote, :data => [[17, 17, 11, 8, 2],[10, 20, 15, 5, 7],[2, 3, 7, 9, 12]], :line_colors => 'e0440e,e62ae5,287eec', :legend => ['courbe 1','courbe 2','courbe 3'], :axis_with_labels => ['x', 'y'], :axis_range => [[0,100,20], [0,20,5]], :filename => "tmp/chart.png") # Record file in filesystem chart.file try yourself ------------- Gchart.bar( :data => [[1,2,4,67,100,41,234],[45,23,67,12,67,300, 250]], :title => 'SD Ruby Fu level', :legend => ['matt','patrick'], :bg => {:color => '76A4FB', :type => 'gradient'}, :bar_colors => 'ff0000,00ff00') "http://chart.apis.google.com/chart?chs=300x200&chdl=matt|patrick&chd=s:AAANUIv,JENCN9y&chtt=SDRuby+Fu+level&chf=bg,lg,0,76A4FB,0,ffffff,1&cht=bvs&chco=ff0000,00ff00" Gchart.pie(:data => [20,10,15,5,50], :title => 'SDRuby Fu level', :size => '400x200', :labels => ['matt', 'rob', 'patrick', 'ryan', 'jordan']) http://chart.apis.google.com/chart?cht=p&chs=400x200&chd=s:YMSG9&chtt=SDRuby+Fu+level&chl=matt|rob|patrick|ryan|jordan googlecharts-1.6.12/metadata.yml0000644000004100000410000000303012564736151016623 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: googlecharts version: !ruby/object:Gem::Version version: 1.6.12 platform: ruby authors: - Matt Aimonetti - Andrey Deryabin - Pedro Pimentel autorequire: bindir: bin cert_chain: [] date: 2015-08-12 00:00:00.000000000 Z dependencies: [] description: Generate charts using Google API & Ruby email: mattaimonetti@gmail.com deriabin@gmail.com zukunft@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".travis.yml" - Gemfile - History.txt - License.txt - README - README.markdown - README.txt - Rakefile - googlecharts.gemspec - lib/gchart.rb - lib/gchart/aliases.rb - lib/gchart/theme.rb - lib/gchart/version.rb - lib/googlecharts.rb - lib/themes.yml - spec/fixtures/another_test_theme.yml - spec/fixtures/test_theme.yml - spec/gchart_spec.rb - spec/spec_helper.rb - spec/theme_spec.rb homepage: http://googlecharts.rubyforge.org/ licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.8 signing_key: specification_version: 4 summary: Generate charts using Google API & Ruby test_files: - spec/fixtures/another_test_theme.yml - spec/fixtures/test_theme.yml - spec/gchart_spec.rb - spec/spec_helper.rb - spec/theme_spec.rb googlecharts-1.6.12/.gitignore0000644000004100000410000000007012564736151016311 0ustar www-datawww-data.DS_Store log/* .manifest pkg .rspec .rvmrc Gemfile.lockgooglecharts-1.6.12/googlecharts.gemspec0000644000004100000410000000147712564736151020363 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "gchart/version" Gem::Specification.new do |s| s.name = %q{googlecharts} s.version = GchartInfo::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Matt Aimonetti", "Andrey Deryabin", "Pedro Pimentel"] s.date = %q{2015-08-12} s.summary = %q{Generate charts using Google API & Ruby} s.description = %q{Generate charts using Google API & Ruby} s.email = %q{mattaimonetti@gmail.com deriabin@gmail.com zukunft@gmail.com} s.homepage = %q{http://googlecharts.rubyforge.org/} s.license = 'MIT' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] end