Skip to content

Commit

Permalink
Merge pull request #100 from Prakriti-nith/listener_googlechart
Browse files Browse the repository at this point in the history
Handling events in GoogleCharts
  • Loading branch information
Shekharrajak authored Jul 26, 2018
2 parents b3251fc + 14ecc63 commit e6a5e2f
Show file tree
Hide file tree
Showing 12 changed files with 948 additions and 140 deletions.
39 changes: 19 additions & 20 deletions lib/daru/view/adapters/googlecharts/base_chart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,6 @@ def extract_option_view
'\'\''
end

# Generates JavaScript function for rendering the chartwrapper
#
# @param (see #to_js_chart_wrapper)
# @return [String] JS function to render the chartwrapper
def draw_js_chart_wrapper(data, element_id)
js = ''
js << "\n function #{chart_function_name(element_id)}() {"
js << "\n \t#{@data_table.to_js}"
js << "\n \tvar wrapper = new google.visualization.ChartWrapper({"
js << "\n \t\tchartType: '#{chart_name}',"
js << append_data(data)
js << "\n \t\toptions: #{js_parameters(@options)},"
js << "\n \t\tcontainerId: '#{element_id}',"
js << "\n \t\tview: #{extract_option_view}"
js << "\n \t});"
js << draw_wrapper
js << "\n };"
js
end

# Generates JavaScript function for rendering the chart when data is URL of
# the google spreadsheet
#
Expand All @@ -54,9 +34,28 @@ def draw_js_spreadsheet(data, element_id=SecureRandom.uuid)
js << "\n var data_table = response.getDataTable();"
js << "\n var chart = new google.#{chart_class}.#{chart_name}"\
"(document.getElementById('#{element_id}'));"
js << add_listeners_js('chart')
js << "\n chart.draw(data_table, #{js_parameters(@options)});"
js << "\n };"
js
end

# Taken from `draw_js` in googlevisualr. While adding the listener,
# the callback code (provided by the user) should be within the function.
#
# @param element_id [String] The ID of the DIV element that the Google
# Chart should be rendered in
# @return [String] JavaScript function for rendering the chart
def draw_chart_js(element_id)
js = ''
js << "\n function #{chart_function_name(element_id)}() {"
js << "\n #{@data_table.to_js}"
js << "\n var chart = new google.#{chart_class}.#{chart_name}"
js << "(document.getElementById('#{element_id}'));"
js << add_listeners_js('chart')
js << "\n chart.draw(data_table, #{js_parameters(@options)});"
js << "\n };"
js
end
end
end
38 changes: 15 additions & 23 deletions lib/daru/view/adapters/googlecharts/data_table_iruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class DataTable
attr_accessor :data
# options will enable us to give some styling for table.
# E.g. pagination, row numbers, etc
attr_accessor :options
attr_accessor :options, :listeners
# @return [Hash] Various options created to facilitate more features.
# These will be provided by the user
attr_accessor :user_options
Expand All @@ -26,6 +26,7 @@ class DataTable
def initialize(options={})
@cols = []
@rows = []
@listeners = []
@options = options
return if options.empty?

Expand All @@ -38,6 +39,15 @@ def initialize(options={})
end
end

# Adds a listener to the array of listeners
#
# @param event [String] name of the event tha will be fired
# @param callback [String] callback function name for the event
# @return [Array] array of listeners
def add_listener(event, callback)
@listeners << {event: event.to_s, callback: callback}
end

# Generates JavaScript and renders the Google Chart DataTable in the
# final HTML output
#
Expand Down Expand Up @@ -96,32 +106,13 @@ def draw_js(element_id)
js << "\n function #{chart_function_name(element_id)}() {"
js << "\n #{to_js}"
js << "\n var table = new google.visualization.Table("
js << "\n document.getElementById('#{element_id}'));"
js << "document.getElementById('#{element_id}'));"
js << add_listeners_js('table')
js << "\n table.draw(data_table, #{js_parameters(@options)}); "
js << "\n };"
js
end

# Generates JavaScript function for rendering the chartwrapper
#
# @param (see #to_js_chart_wrapper)
# @return [String] JS function to render the chartwrapper
def draw_js_chart_wrapper(data, element_id)
js = ''
js << "\n function #{chart_function_name(element_id)}() {"
js << "\n \t#{to_js}"
js << "\n \tvar wrapper = new google.visualization.ChartWrapper({"
js << "\n \t\tchartType: 'Table',"
js << append_data(data)
js << "\n \t\toptions: #{js_parameters(@options)},"
js << "\n \t\tcontainerId: '#{element_id}',"
js << "\n \t\tview: #{extract_option_view}"
js << "\n \t});"
js << draw_wrapper
js << "\n };"
js
end

# Generates JavaScript function for rendering the google chart table when
# data is URL of the google spreadsheet
#
Expand All @@ -138,7 +129,8 @@ def draw_js_spreadsheet(data, element_id)
js << "\n var data_table = response.getDataTable();"
js << "\n var table = new google.visualization.Table"\
"(document.getElementById('#{element_id}'));"
js << "\n table.draw(data_table, #{js_parameters(@options)});"
js << add_listeners_js('table')
js << "\n table.draw(data_table, #{js_parameters(@options)});"
js << "\n };"
js
end
Expand Down
67 changes: 65 additions & 2 deletions lib/daru/view/adapters/googlecharts/display.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

module GoogleVisualr
def self.init_script(
dependent_js=GOOGLECHARTS_DEPENDENCIES
dependent_js=GOOGLECHARTS_DEPENDENCIES_WEB
)
js = ''
js << "\n<script type='text/javascript'>"
Expand Down Expand Up @@ -59,7 +59,11 @@ def show_script_with_script_tag(dom=SecureRandom.uuid)
def get_html(dom)
html = ''
html << load_js(dom)
html << draw_js(dom)
html << if is_a?(GoogleVisualr::DataTable)
draw_js(dom)
else
draw_chart_js(dom)
end
html
end

Expand Down Expand Up @@ -93,6 +97,7 @@ def to_html(id=nil, options={})
template = File.read(path)
id ||= SecureRandom.uuid
@html_id = id
add_listener_to_chart
chart_script = show_script(id, script_tag: false)
ERB.new(template).result(binding)
end
Expand All @@ -101,6 +106,43 @@ def show_in_iruby(dom=SecureRandom.uuid)
IRuby.html to_html(dom)
end

# @return [void] Adds listener to the chart from the
# user_options[:listeners]
def add_listener_to_chart
return unless user_options && user_options[:listeners]
user_options[:listeners].each do |event, callback|
add_listener(event.to_s.downcase, callback)
end
end

# @return [String] js function to add the listener to the chart
def add_listeners_js(type)
js = ''
@listeners.each do |listener|
js << "\n google.visualization.events.addListener("
js << "#{type}, '#{listener[:event]}', function (e) {"
js << "\n #{listener[:callback]}"
js << "\n });"
end
js
end

# @param (see #draw_js_chart_editor)
# @return [String] options of the ChartWrapper
def extract_chart_wrapper_options(data, element_id)
js = ''
js << if is_a?(GoogleVisualr::DataTable)
"\n \t\tchartType: 'Table',"
else
"\n \t\tchartType: '#{chart_name}',"
end
js << append_data(data)
js << "\n \t\toptions: #{js_parameters(@options)},"
js << "\n \t\tcontainerId: '#{element_id}',"
js << "\n \t\tview: #{extract_option_view}"
js
end

# @param element_id [String] The ID of the DIV element that the Google
# Chart/DataTable should be rendered in
# @return [String] unique function name to handle query response
Expand Down Expand Up @@ -163,6 +205,27 @@ def to_js_spreadsheet(data, element_id=SecureRandom.uuid)
js << "\n</script>"
js
end

# Generates JavaScript function for rendering the chartwrapper
#
# @param (see #to_js_chart_wrapper)
# @return [String] JS function to render the chartwrapper
def draw_js_chart_wrapper(data, element_id)
js = ''
js << "\n function #{chart_function_name(element_id)}() {"
js << if is_a?(GoogleVisualr::DataTable)
"\n \t#{to_js}"
else
"\n \t#{@data_table.to_js}"
end
js << "\n \tvar wrapper = new google.visualization.ChartWrapper({"
js << extract_chart_wrapper_options(data, element_id)
js << "\n \t});"
js << draw_wrapper
js << add_listeners_js('wrapper')
js << "\n };"
js
end
end

class DataTable
Expand Down
2 changes: 1 addition & 1 deletion lib/daru/view/adapters/googlecharts/iruby_notebook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def self.generate_init_code(dependent_js)
end

# Enable to show plots on IRuby notebook
def self.init_iruby(dependent_js=GOOGLECHARTS_DEPENDENCIES)
def self.init_iruby(dependent_js=GOOGLECHARTS_DEPENDENCIES_IRUBY)
js = generate_init_code(dependent_js)
IRuby.display(IRuby.javascript(js))
end
Expand Down
172 changes: 172 additions & 0 deletions lib/daru/view/adapters/js/googlecharts_js/jspdf.min.js

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions lib/daru/view/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
# HighCharts CSS dependencies
HIGHCHARTS_DEPENDENCIES_CSS = ['highcharts.css'].freeze

# Dependent GoogleCharts JS constants for web frameworks and IRuby notebook
GOOGLECHARTS_DEPENDENCIES = ['google_visualr.js', 'loader.js'].freeze
# Dependent GoogleCharts JS constants for IRuby notebook
GOOGLECHARTS_DEPENDENCIES_IRUBY = ['google_visualr.js', 'loader.js'].freeze

# Dependent GoogleCharts JS constants for web frameworks
GOOGLECHARTS_DEPENDENCIES_WEB = ['google_visualr.js', 'loader.js', 'jspdf.min.js'].freeze

# Regex pattern to match a valid URL
PATTERN_URL = Regexp.new(
Expand Down
18 changes: 12 additions & 6 deletions lib/tasks/google_charts.rake
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@ end

namespace :googlecharts do
desc "Update google charts javascript dependent files, from latest Builds on google developers website"
task :update => [:jsapi, :loader]
task :update => [:loader, :jspdf]
sh "mkdir -p lib/daru/view/adapters/js/googlecharts_js/"
task :jsapi do
say "Grabbing Core from google jsapi codebase..." do
sh "curl -# http://www.google.com/jsapi -L --compressed -o lib/daru/view/adapters/js/googlecharts_js/google_visualr.js"
end
end
# FIXME: Updating jsapi is causing error in IRuby notebook and Googlecharts do not work.
# task :jsapi do
# say "Grabbing Core from google jsapi codebase..." do
# sh "curl -# http://www.google.com/jsapi -L --compressed -o lib/daru/view/adapters/js/googlecharts_js/google_visualr.js"
# end
# end

task :loader do
say "Grabbing loader.js from the google website..." do
sh "curl -# http://www.gstatic.com/charts/loader.js -L --compressed -o lib/daru/view/adapters/js/googlecharts_js/loader.js"
end
end

task :jspdf do
say "Grabbing jspdf.min.js from the cloudfare..." do
sh "curl -# https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js -L --compressed -o lib/daru/view/adapters/js/googlecharts_js/jspdf.min.js"
end
end
end
39 changes: 10 additions & 29 deletions spec/adapters/googlecharts/base_chart_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
{type: :column, width: 800}
)
}
let(:user_options) {{
listeners: {
select: "alert('A table row was selected');"
}
}}
let(:column_chart) { Daru::View::Plot.new(
data_spreadsheet,
{ type: :column },
user_options)
}
let(:data) {
[
['Year', 'Sales', 'Expenses'],
Expand Down Expand Up @@ -47,35 +57,6 @@
end
end

describe "#to_js_chart_wrapper" do
it "draws valid JS of the ChartWrapper when data is URL of the spreadsheet" do
js = area_chart_spreadsheet.chart.to_js_chart_wrapper(
data_spreadsheet,
'id'
)
expect(js).to match(/google.load\('visualization'/)
expect(js).to match(/callback: draw_id/)
expect(js).to match(/new google.visualization.ChartWrapper/)
expect(js).to match(/chartType: 'AreaChart'/)
expect(js).to match(/dataSourceUrl: 'https:\/\/docs.google/)
expect(js).to match(/options: {}/)
expect(js).to match(/containerId: 'id'/)
end
end

describe "#draw_js_chart_wrapper" do
it "draws valid JS of the ChartWrapper" do
js = area_chart.chart.draw_js_chart_wrapper(data, 'id')
expect(js).to match(/new google.visualization.DataTable/)
expect(js).to match(/new google.visualization.ChartWrapper/)
expect(js).to match(/chartType: 'AreaChart'/)
expect(js).to match(/dataTable: data_table/)
expect(js).to match(/options: {width: 800/)
expect(js).to match(/containerId: 'id'/)
expect(js).to match(/view: {columns: \[0,1\]}/)
end
end

describe "#draw_js_spreadsheet" do
it "draws valid JS of the chart when "\
"data is imported from google spreadsheets" do
Expand Down
Loading

0 comments on commit e6a5e2f

Please sign in to comment.