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 Highstock feature #89

Merged
merged 11 commits into from
May 22, 2018
Merged
36 changes: 31 additions & 5 deletions lib/daru/view/adapters/highcharts/display.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

module LazyHighCharts
def self.init_script(
dependent_js=['highstock.js', 'modules/exporting.js',
dependent_js=['highstock.js', 'highcharts-more.js', 'modules/exporting.js',
'highcharts-3d.js', 'modules/data.js']
)
# Highstock is based on Highcharts, meaning it has all the core
Expand Down Expand Up @@ -33,13 +33,23 @@ class HighChart
#
def to_html(placeholder=random_canvas_id)
chart_hash_must_be_present
high_chart(placeholder, self)
# Helps to denote either of the three classes.
chart_class = extract_chart_class
# When user wants to plot a HighMap
if chart_class == 'Map'
high_map(placeholder, self)
# When user wants to plot a HighStock
elsif chart_class == 'StockChart'
high_stock(placeholder, self)
# No need to pass any value for HighChart
else
Copy link
Member

Choose a reason for hiding this comment

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

I think it must be specific 'Chart'. If user have entered some xyz chart_class then raise error 'Not implemented' or '3 chart_class chart, stock, map must be selected ' something like that.

high_chart(placeholder, self)
end
end

def show_in_iruby(placeholder=random_canvas_id)
# TODO : placeholder pass, in plot#div
chart_hash_must_be_present
IRuby.html high_chart_iruby(placeholder, self)
IRuby.html to_html_iruby(placeholder)
end

# This method is not needed if `to_html` generates the same code. Here
Expand All @@ -48,7 +58,23 @@ def show_in_iruby(placeholder=random_canvas_id)
def to_html_iruby(placeholder=random_canvas_id)
# TODO : placeholder pass, in plot#div
chart_hash_must_be_present
high_chart_iruby(placeholder, self)
high_chart_iruby(extract_chart_class, placeholder, self)
end

# @return [String] the class of the chart
def extract_chart_class
# Provided by user and can take two values ('stock' or 'map').
chart_class = options.delete(:chart_class).to_s.downcase unless
Copy link
Member

Choose a reason for hiding this comment

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

Make it DRY. May be one method or instance variable.

Copy link
Member

Choose a reason for hiding this comment

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

Instead of downcase , capitalize can reduce the number of line. Please read my comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but we need to check whether chart_class is assigned or not and user has entered the correct value for chart_class. For that, we still have to compare with all the 3 classes.

options[:chart_class].nil?
chart_class =
if chart_class == 'map'
'Map'
elsif chart_class == 'stock'
'StockChart'
else
'Chart'
end
chart_class
end

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

# Enable to show plots on IRuby notebook
def self.init_iruby(
dependent_js=['highcharts.js', 'modules/exporting.js',
dependent_js=['highstock.js', 'highcharts-more.js', 'modules/exporting.js',
'highcharts-3d.js', 'modules/data.js']
)
# TODO: include highstock.js for highstock and modules/*.js files for
Expand Down
22 changes: 10 additions & 12 deletions lib/daru/view/adapters/highcharts/layout_helper_iruby.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
module LazyHighCharts
module LayoutHelper
def high_chart_iruby(placeholder, object, &block)
def high_chart_iruby(chart_class, placeholder, object, &block)
object.html_options[:id] = placeholder
object.options[:chart][:renderTo] = placeholder
high_graph_iruby(placeholder, object, &block).concat(content_tag('div', '', object.html_options))
end

def high_graph_iruby(placeholder, object, &block)
build_html_output_iruby('Chart', placeholder, object, &block)
build_html_output_iruby(
chart_class, placeholder, object, &block
).concat(content_tag('div', '', object.html_options))
end

private
Expand All @@ -29,18 +27,18 @@ def encapsulate_js_iruby(core_js)
"#{js_start_iruby} #{core_js} #{js_end_iruby}"
# Turbolinks.version < 5
elsif defined?(Turbolinks) && request_is_referrer?
to_s(eventlistener_page_load)
eventlistener_page_load(core_js)
Copy link
Member

Choose a reason for hiding this comment

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

without passing core_js , it will work, right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it was not working as these methods (eventlistener_page_load, eventlistener_turbolinks_load, call_core_js) required core_js.

elsif defined?(Turbolinks) && request_turbolinks_5_tureferrer?
to_s(eventlistener_turbolinks_load)
eventlistener_turbolinks_load(core_js)
else
to_s(call_core_js)
call_core_js(core_js)
end

defined?(raw) ? raw(js_output) : js_output
end
# rubocop:enable Metrics/PerceivedComplexity

def eventlistener_page_load
def eventlistener_page_load(core_js)
<<-EOJS
#{js_start_iruby}
var f = function(){
Expand All @@ -52,7 +50,7 @@ def eventlistener_page_load
EOJS
end

def eventlistener_turbolinks_load
def eventlistener_turbolinks_load(core_js)
<<-EOJS
#{js_start_iruby}
document.addEventListener("turbolinks:load", function() {
Expand All @@ -62,7 +60,7 @@ def eventlistener_turbolinks_load
EOJS
end

def call_core_js
def call_core_js(core_js)
<<-EOJS
#{js_start_iruby}
#{core_js}
Expand Down
1 change: 0 additions & 1 deletion lib/daru/view/templates/highcharts/init.inline.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ var event = document.createEvent("HTMLEvents");
event.initEvent("load_highcharts", false, false);
window.dispatchEvent(event);
console.log("Finish loading highchartsjs");

216 changes: 216 additions & 0 deletions spec/adapters/highcharts/display_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
require 'spec_helper.rb'

describe LazyHighCharts do
before { Daru::View.plotting_library = :highcharts }
describe "#init_script" do
it "generates valid initial script" do
js = LazyHighCharts.init_script
Copy link
Member

Choose a reason for hiding this comment

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

This is not testing whether all the js files are loaded or not.

Isn't we check for "BEGIN highstock.js" and "END highstock.js" , ... ?

expect(js).to match(/BEGIN highstock.js/i)
expect(js).to match(/Highstock JS/i)
expect(js).to match(/END highstock.js/i)
expect(js).to match(/BEGIN highcharts-more.js/i)
expect(js).to match(/END highcharts-more.js/i)
expect(js).to match(/BEGIN modules\/exporting.js/i)
expect(js).to match(/END modules\/exporting.js/i)
expect(js).to match(/BEGIN highcharts-3d.js/i)
expect(js).to match(/END highcharts-3d.js/i)
expect(js).to match(/BEGIN modules\/data.js/i)
expect(js).to match(/END modules\/data.js/i)
expect(js).to match(/<script type='text\/javascript'>/i)
expect(js).to match(
/var event = document.createEvent\(\"HTMLEvents\"\)/i)
expect(js).to match(
/event.initEvent\(\"load_highcharts\", false, false\)/i)
expect(js).to match(/window.dispatchEvent\(event\)/i)
expect(js).to match(
/console.log\(\"Finish loading highchartsjs\"\)/i)
end
end
end

describe LazyHighCharts::HighChart do
before { Daru::View.plotting_library = :highcharts }
before(:each) do
@opts = {
chart: {
type: 'bar'
},
title: {
text: 'Bar chart'
},
yAxis: {
min: 0,
title: {
text: 'Total consumption'
}
},
legend: {
reversed: true
}
}
@data_vec1 = Daru::Vector.new([5, 3, 4])
@data_vec2 = Daru::Vector.new([2, 2, 3])
@data_vec3 = Daru::Vector.new([3,4,4])
@data_df = Daru::DataFrame.new({John: @data_vec1, Jane: @data_vec2, Joe: @data_vec3})
@hc = Daru::View::Plot.new(@data_df, @opts)
@placeholder = "placeholder"
end

describe "#to_html" do
Copy link
Member

Choose a reason for hiding this comment

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

Please write specs for all methods present in display.rb , iruby_notebook.rb, layout_helper_iruby.rb (or few specs such that it covers all the methods).

before(:each) do
@opts = {
chart_class: 'stock',
chart: {
type: 'arearange'
},
rangeSelector: {
selected: 1
},

title: {
text: 'AAPL Stock Price'
}
}
@series_dt = [
{
name: 'AAPL Stock Price',
data: [
[1147651200000,67.79],
[1147737600000,64.98],
[1147824000000,65.26],

[1149120000000,62.17],
[1149206400000,61.66],
[1149465600000,60.00],
[1149552000000,59.72],

[1157932800000,72.50],
[1158019200000,72.63],
[1158105600000,74.20],
[1158192000000,74.17],
[1158278400000,74.10],
[1158537600000,73.89],

[1170288000000,84.74],
[1170374400000,84.75],

[1174953600000,95.46],
[1175040000000,93.24],
[1175126400000,93.75],
[1175212800000,92.91],

[1180051200000,113.62],
[1180396800000,114.35],
[1180483200000,118.77],
[1180569600000,121.19],
],
marker: {
enabled: true,
radius: 3
},
shadow: true,
tooltip: {
valueDecimals: 2
}
}
]
@chart = Daru::View::Plot.new
@chart.chart.options = @opts;
@chart.chart.series_data = @series_dt
end
it "should plot Highstock when chart_class is set to stock" do
@hc.options[:chart_class] = "STock";
expect(@hc.chart.to_html(
@placeholder)
).to match(/window\.chart_placeholder\s+=\s+new\s+Highcharts.StockChart/)
end
it "should plot HighChart otherwise" do
expect(@hc.chart.to_html(
@placeholder)
).to match(/window\.chart_placeholder\s+=\s+new\s+Highcharts.Chart/)
end
it "should return a div with an id of high_chart object" do
expect(@chart.chart.to_html(@placeholder)).to match(/<div id="placeholder">/)
expect(@hc.chart.to_html(@placeholder)).to match(/<div id="placeholder">/)
end
it "should return a script" do
expect(@chart.chart.to_html(@placeholder)).to match(/script/)
expect(@hc.chart.to_html(@placeholder)).to match(/script/)
end
it "should set variables `chart` `options`" do
expect(@chart.chart.to_html(@placeholder)).to match(/var\s+options\s+=/)
expect(@chart.chart.to_html(@placeholder)).to match(/window.chart_placeholder/)
expect(@hc.chart.to_html(@placeholder)).to match(/var\s+options\s+=/)
expect(@hc.chart.to_html(@placeholder)).to match(/window.chart_placeholder/)
end
it "should take a block setting attributes" do
expect(@chart.chart.options[:rangeSelector][:selected]).to eq(1)
expect(@chart.chart.to_html(@placeholder)).to match(/rangeSelector/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/series\": \[\{ \"name\": \"AAPL Stock Price\"/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/\"data\": \[ \[ 1147651200000,67.79 \]/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/\"title\": \{ \"text\": \"AAPL Stock Price\" \}/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/\"chart\": \{ \"type\": \"arearange\"/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/\"marker\": \{ \"enabled\": true/)
expect(@chart.chart.to_html(@placeholder)).to match(/\"shadow\": true/)
expect(@chart.chart.to_html(
@placeholder)
).to match(/\"tooltip\": \{ \"valueDecimals\": 2/)
expect(@hc.chart.to_html(
@placeholder)
).to match(/\"chart\": \{ \"type\": \"bar\"/)
expect(@hc.chart.to_html(
@placeholder)
).to match(/\"data\": \[ \[ 5,2,3 \],\[ 3,2,4 \],\[ 4,3,4 \] \]/)
expect(@hc.chart.to_html(
@placeholder)
).to match(/\"title\": \{ \"text\": \"Bar chart\" \}/)
expect(@hc.chart.to_html(
@placeholder)
).to match(/\"legend\": \{ \"reversed\": true \}/)
expect(@hc.chart.to_html(
@placeholder)
).to match(/\"yAxis\": \{ \"min\": 0/)
end
end

describe "#to_html_iruby" do
it "should plot Highstock when chart_class is set to stock" do
@hc.options[:chart_class] = "SToCk";
expect(@hc.chart.to_html_iruby(
@placeholder)
).to match(/window\.chart_placeholder\s+=\s+new\s+Highcharts.StockChart/)
end
it "should plot HighChart otherwise" do
expect(@hc.chart.to_html_iruby(
@placeholder)
).to match(/window\.chart_placeholder\s+=\s+new\s+Highcharts.Chart/)
end
end

describe "#extract_chart_class" do
it "should return StockChart class when chart_class is set to stock" do
@hc.options[:chart_class] = "SToCk";
expect(@hc.chart.extract_chart_class).to eq 'StockChart'
end
it "should return Chart class when chart_class is not set" do
expect(@hc.chart.extract_chart_class).to eq 'Chart'
end
end

describe "#chart_hash_must_be_present" do
it "should check the presence of chart hash in options" do
@hc.chart.chart_hash_must_be_present
expect(@hc.options[:chart]).to eq :type=>"bar"
end
end
end
28 changes: 28 additions & 0 deletions spec/adapters/highcharts/iruby_notebook_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'spec_helper.rb'

describe LazyHighCharts do
before { Daru::View.plotting_library = :highcharts }
describe "#init_script" do
it "generates valid initial script" do
js = LazyHighCharts.init_script
expect(js).to match(/BEGIN highstock.js/i)
expect(js).to match(/Highstock JS/i)
expect(js).to match(/END highstock.js/i)
expect(js).to match(/BEGIN highcharts-more.js/i)
expect(js).to match(/END highcharts-more.js/i)
expect(js).to match(/BEGIN modules\/exporting.js/i)
expect(js).to match(/END modules\/exporting.js/i)
expect(js).to match(/BEGIN highcharts-3d.js/i)
expect(js).to match(/END highcharts-3d.js/i)
expect(js).to match(/BEGIN modules\/data.js/i)
expect(js).to match(/END modules\/data.js/i)
expect(js).to match(
/var event = document.createEvent\(\"HTMLEvents\"\)/i)
expect(js).to match(
/event.initEvent\(\"load_highcharts\", false, false\)/i)
expect(js).to match(/window.dispatchEvent\(event\)/i)
expect(js).to match(
/console.log\(\"Finish loading highchartsjs\"\)/i)
end
end
end
Loading