require 'json' require 'time' require 'erb' module Swagchart module Helper def chart(type, data, opts={}, &block) @google_visualization_included ||= false @chart_counter ||= 0 type = camelize(type.to_s) opts[:columns] = opts[:columns].split(',').map(&:strip) if opts[:columns].is_a?(String) data = data.to_a if data.is_a?(Hash) if data.respond_to?(:first) && data.first.is_a?(Hash) data = hash_array_to_data_table(data) opts.delete(:columns) elsif data.respond_to?(:unshift) && data.respond_to?(:first) if opts[:columns] data.unshift opts.delete(:columns) elsif !data.first.find{|e| !e.is_a?(String) && !e.is_a?(Symbol) } # Do nothing! This should already be in a DataTable format. # First row seems to only define column names. else data.unshift Array.new(data.first.size, '') end end chart_id = ERB::Util.html_escape(opts.delete(:chart_id) || "chart_#{@chart_counter += 1}") style = 'height:320px;' #dirty hack right here .. you can override that with your style though style << ERB::Util.html_escape(opts.delete(:style)) if opts[:style] html = '' unless @google_visualization_included #we only need to include this once html << jsapi_includes_template @google_visualization_included = true end options = opts.delete(:options) || {} html << classic_template(id: chart_id, type: type, style: style, options: options, data: data) html.respond_to?(:html_safe) ? html.html_safe : html end private def hash_array_to_data_table(ha) cols = ha.first.keys rows = ha.map{|r| cols.reduce([]){|s,e| s</ #dtrx= /#/ #trx = /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d) \+\d\d\d\d/ #blk = ->(s){v=$~.captures.map(&:to_i); v[1]-=1; "new Date(#{v.join(',')})"} #str.to_s.gsub(dtrx, &blk).gsub(drx, &blk).gsub(trx, &blk) end def classic_template(opts={}) <Loading... HTML end def chartwrapper_template(opts={}) <Loading... HTML end def jsapi_includes_template < google.load('visualization','1'); google.load('visualization', '1', {packages: [ 'corechart', 'geochart', 'map', 'treemap', 'annotatedtimeline', 'sankey', 'orgchart', 'calendar', 'gauge' ]}); HTML end end end