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

Added export method to export highchart in different formats #94

Merged
merged 4 commits into from Jul 14, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/daru/view/adapters/googlecharts.rb
Expand Up @@ -182,6 +182,10 @@ def export_html_file(plot, path='./plot.html')
File.write(path, str)
end

def export(_plot, _export_type='png', _file_name='chart')
raise 'Not implemented yet'
end

def show_in_iruby(plot)
plot.show_in_iruby
end
Expand Down
15 changes: 15 additions & 0 deletions lib/daru/view/adapters/highcharts.rb
Expand Up @@ -70,6 +70,21 @@ def export_html_file(plot, path='./plot.html')
File.write(path, str)
end

# Exporting in web frameworks is completely offline. In IRuby notebook,
# offline-export supports only the exporting to png, jpeg and svg format.
# Export to PDF is not working (not even through the exporting button in
# highchart). So, online exporting is done in IRuby notebook. There is a
# problem in online exporting that if we run-all all the cells of IRuby
# notebook then only the last chart will be exported. Individually,
# running the cells works fine.
#
# @see #Daru::View::Plot.export
def export(plot, export_type='png', file_name='chart')
plot.export_iruby(export_type, file_name) if defined? IRuby
rescue NameError
plot.export(export_type, file_name)
end

def show_in_iruby(plot)
plot.show_in_iruby
end
Expand Down
95 changes: 95 additions & 0 deletions lib/daru/view/adapters/highcharts/display.rb
Expand Up @@ -49,6 +49,10 @@ def self.init_script
end

class HighChart
# Holds a value only when to_html or to_html_iruby method is invoked
# @return [String] The ID of the DIV element that the HighChart should
# be rendered in
attr_accessor :div_id
# @example
#
# To display the html code of the chart, use `to_html`. To see the same
Expand All @@ -62,6 +66,7 @@ class HighChart
def to_html(placeholder=random_canvas_id)
chart_hash_must_be_present
script = load_dependencies('web_frameworks')
@div_id = placeholder
script << high_chart_css(placeholder)
# Helps to denote either of the three classes.
chart_class = extract_chart_class
Expand All @@ -88,6 +93,7 @@ def show_in_iruby(placeholder=random_canvas_id)
# `high_chart_iruby` which doesn't use `onload` in chart script.
def to_html_iruby(placeholder=random_canvas_id)
# TODO : placeholder pass, in plot#div
@div_id = placeholder
load_dependencies('iruby')
chart_hash_must_be_present
script = high_chart_css(placeholder)
Expand Down Expand Up @@ -160,6 +166,95 @@ def get_map_data_dependencies(dep_js)
end
end

# @see #Daru::View::Plot.export
def export(export_type='png', file_name='chart')
js = ''
js << to_html
js << extract_export_code(@div_id, export_type, file_name)
js
end

# Exports chart to different formats in IRuby notebook
#
# @param type [String] format to which chart has to be exported
# @param file_name [String] The name of the file after exporting the chart
# @return [void] loads the js code of chart along with the code to export
# in IRuby notebook
def export_iruby(export_type='png', file_name='chart')
js = ''
js << to_html_iruby
js << extract_export_code_iruby(@div_id, export_type, file_name)
IRuby.html js
end

# Returns the script to export the chart in different formats for
# web frameworks
#
# @param file_name [String] The name of the file after exporting the chart
# @param placeholder [String] The ID of the DIV element that
# the HighChart should be rendered in
# @param type [String] format to which chart has to be exported
# @return [String] the script to export the chart in web frameworks
def extract_export_code(
placeholder=random_canvas_id, export_type='png', file_name='chart'
)
js = ''
js << "\n <script>"
js << "\n (function() {"
js << "\n \tvar onload = window.onload;"
js << "\n \twindow.onload = function(){"
js << "\n \t\tif (typeof onload == 'function') onload();"
js << "\n \t\tvar chartDom = document.getElementById('#{placeholder}');"
js << "\n \t\tvar chart = Highcharts.charts[Highcharts.attr(chartDom,"
js << " 'data-highcharts-chart')]"
js << "\n \t\tchart.exportChartLocal({"
js << "\n \t\t\t" + append_chart_type(export_type)
js << "\n \t\t\tfilename: '#{file_name}'"
js << "\n \t\t});\n \t};\n })();"
js << "\n </script>"
js
end

# Returns the script to export the chart in different formats in
# IRuby notebook
#
# @param (see #extract_export_code)
# @return [String] the script to export the chart in IRuby notebook
def extract_export_code_iruby(
placeholder=random_canvas_id, export_type='png', file_name='chart'
)
js = ''
js << "\n <script>"
js << "\n (function() {"
js << "\n \tvar chartDom = document.getElementById('#{placeholder}');"
js << "\n \tvar chart = Highcharts.charts[Highcharts.attr(chartDom,"
js << " 'data-highcharts-chart')]"
js << "\n \tchart.exportChart({"
js << "\n \t\t" + append_chart_type(export_type)
js << "\n \t\tfilename: '#{file_name}'"
js << "\n \t});"
js << "\n })();"
js << "\n </script>"
js
end

# @param type [String] format to which chart has to be exported
# @return [String] code stating the type to which chart has to be exported
def append_chart_type(export_type='png')
case export_type
when 'pdf'
"type: 'application/pdf',"
when 'png'
"type: 'image/png',"
when 'jpg', 'jpeg'
"type: 'image/jpeg',"
when 'svg'
"type: 'image/svg+xml',"
else
raise TypeError, 'Invalid format'
end
end

# @return [String] the class of the chart
def extract_chart_class
# Provided by user and can take two values ('stock' or 'map').
Expand Down
3 changes: 3 additions & 0 deletions lib/daru/view/adapters/highcharts/iruby_notebook.rb
Expand Up @@ -36,6 +36,9 @@ def self.init_iruby(
# , 'modules/exporting.js' : for the exporting button
# data.js for getting data as csv or html table.
# 'highcharts-more.js' : for arearange and some other chart type
# 'modules/offline-exporting.js': for enabling offline exporting. Used in
# #chart.extract_export_code method (to enable chart.exportChartLocal)
# to export the chart using code.
# Note: Don't reorder the dependent_js elements. It must be loaded in
# the same sequence. Otherwise some of the JS overlap and doesn't work.
js = generate_init_code(dependent_js)
Expand Down
4 changes: 4 additions & 0 deletions lib/daru/view/adapters/nyaplot.rb
Expand Up @@ -16,6 +16,10 @@ def export_html_file(plot, path)
plot.export_html path
end

def export(_plot, _export_type='png', _file_name='chart')
raise 'Not implemented yet'
end

def show_in_iruby(plot)
plot.show
end
Expand Down
3 changes: 2 additions & 1 deletion lib/daru/view/constants.rb
Expand Up @@ -6,14 +6,15 @@
EXPORTING = 'modules/exporting.js'.freeze
HIGHCHARTS_3D = 'highcharts-3d.js'.freeze
DATA = 'modules/data.js'.freeze
OFFLINE_EXPORTING = 'modules/offline-exporting.js'.freeze

# HighCharts IRuby notebook dependencies
HIGHCHARTS_DEPENDENCIES_IRUBY = [HIGHSTOCK, MAP, EXPORTING, HIGHCHARTS_3D,
DATA].freeze

# HighCharts Web Frameworks dependencies
HIGHCHARTS_DEPENDENCIES_WEB = [HIGHSTOCK_CSS, MAP_CSS, EXPORTING,
HIGHCHARTS_3D, DATA].freeze
HIGHCHARTS_3D, DATA, OFFLINE_EXPORTING].freeze

# HighCharts CSS dependencies
HIGHCHARTS_DEPENDENCIES_CSS = ['highcharts.css'].freeze
Expand Down
12 changes: 12 additions & 0 deletions lib/daru/view/plot.rb
Expand Up @@ -77,6 +77,18 @@ def export_html_file(path='./plot.html')
@adapter.export_html_file(@chart, path)
end

# @param type [String] format to which chart has to be exported
# @param file_name [String] The name of the file after exporting the chart
# @return [String, void] js code of chart along with the code to export it
# and loads the js code to export it in IRuby.
# @example Export a HighChart
# data = Daru::Vector.new([5 ,3, 4])
# hchart = Daru::View::Plot.new(data)
# hchart.export('png', 'daru')
def export(export_type='png', file_name='chart')
@adapter.export(@chart, export_type, file_name)
end

# load the corresponding JS files in IRuby notebook.
# This is done automatically when plotting library is set using
# Daru::View.plotting_library = :new_library
Expand Down
77 changes: 77 additions & 0 deletions spec/adapters/highcharts/display_spec.rb
Expand Up @@ -328,6 +328,83 @@
end
end

describe "#export" do
it "should generate the valid script to export the chart in different"\
" formats" do
js = @hc.chart.export('jpg','daru')
expect(js).to match(/\s+new\s+Highcharts.Chart/)
expect(js).to match(/var\s+options\s+=/)
expect(js).to match(/window.chart_/)
expect(js).to match(/\"chart\": \{ \"type\": \"bar\"/)
expect(js).to match(/\"data\": \[ \[ 5,2,3 \],\[ 3,2,4 \],\[ 4,3,4 \]/)
expect(js).to match(/script/)
expect(js).to match(/image\/jpeg/)
expect(js).to match(/daru/)
expect(js).to match(/chart.exportChartLocal/)
end
end

describe "#extract_export_code" do
it "should generate the valid script to export the chart in different"\
" formats in web frameworks" do
js = @hc.chart.extract_export_code(@placeholder)
expect(js).to match(/script/)
expect(js).to match(/var onload = window.onload/)
expect(js).to match(/window.onload = function()/)
expect(js).to match(/typeof onload == 'function'/)
expect(js).to match(
/var chartDom = document.getElementById\('placeholder'\)/
)
expect(js).to match(
/Highcharts.charts\[Highcharts.attr\(chartDom, 'data-highcharts-chart'\)/
)
expect(js).to match(/image\/png/)
expect(js).to match(/chart.exportChartLocal/)
end
end

describe "#extract_export_code_iruby" do
it "should generate the valid script to export the chart in different"\
" formats in IRuby notebook" do
js = @hc.chart.extract_export_code_iruby(@placeholder, 'png', 'daru')
expect(js).to match(/script/)
expect(js).to match(
/var chartDom = document.getElementById\('placeholder'\)/
)
expect(js).to match(
/Highcharts.charts\[Highcharts.attr\(chartDom, 'data-highcharts-chart'\)/
)
expect(js).to match(/image\/png/)
expect(js).to match(/filename: 'daru'/)
expect(js).to match(/chart.exportChart/)
end
end

describe "#append_chart_type" do
it "should return correct code stating the type to which chart has"\
" to be exported" do
expect(@hc.chart.append_chart_type).to eq("type: 'image/png',")
expect(@hc.chart.append_chart_type(
'pdf')
).to eq("type: 'application/pdf',")
expect(@hc.chart.append_chart_type(
'png')
).to eq("type: 'image/png',")
expect(@hc.chart.append_chart_type(
'jpg')
).to eq("type: 'image/jpeg',")
expect(@hc.chart.append_chart_type(
'jpeg')
).to eq("type: 'image/jpeg',")
expect(@hc.chart.append_chart_type(
'svg')
).to eq("type: 'image/svg+xml',")
expect{@hc.chart.append_chart_type(
'daru')
}.to raise_error(TypeError, 'Invalid format')
end
end

describe "#extract_chart_class" do
it "should return Map class when chart_class is set to map" do
@hc.options[:chart_class] = "map";
Expand Down
13 changes: 13 additions & 0 deletions spec/adapters/highcharts_spec.rb
Expand Up @@ -447,4 +447,17 @@
expect(html).to match(/series": \[\[ 1,15 \],\[ 2,30 \],\[ 4,40 \]\]/)
end
end

describe "#export" do
it "should generate the valid script to export the chart" do
js = @chart_bar.adapter.export(@chart_bar.chart, 'png')
expect(js).to match(/\s+new\s+Highcharts.Chart/)
expect(js).to match(/var\s+options\s+=/)
expect(js).to match(/window.chart_/)
expect(js).to match(/\"chart\": \{ \"type\": \"bar\"/)
expect(js).to match(/script/)
expect(js).to match(/image\/png/)
expect(js).to match(/chart.exportChartLocal/)
end
end
end