Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling events in GoogleCharts #100

Merged
merged 8 commits into from
Jul 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open an issue to track this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#99

# 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we using it ?

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