apexcharts 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +149 -56
  3. data/lib/apex_charts/charts/base_chart.rb +1 -1
  4. data/lib/apex_charts/charts/box_plot_chart.rb +9 -0
  5. data/lib/apex_charts/charts.rb +1 -0
  6. data/lib/apex_charts/helper.rb +9 -8
  7. data/lib/apex_charts/options_builder.rb +146 -123
  8. data/lib/apex_charts/renderer.rb +69 -25
  9. data/lib/apex_charts/series/bubble_series.rb +2 -3
  10. data/lib/apex_charts/series/cartesian_series.rb +8 -2
  11. data/lib/apex_charts/theme.rb +0 -16
  12. data/lib/apex_charts/version.rb +2 -1
  13. data/vendor/assets/javascripts/apexcharts.js +5 -5
  14. metadata +4 -51
  15. data/lib/apex_charts/options/annotations_options.rb +0 -12
  16. data/lib/apex_charts/options/axis_options.rb +0 -19
  17. data/lib/apex_charts/options/chart_options.rb +0 -28
  18. data/lib/apex_charts/options/data_labels_options.rb +0 -16
  19. data/lib/apex_charts/options/div_attributes.rb +0 -11
  20. data/lib/apex_charts/options/fill_options.rb +0 -14
  21. data/lib/apex_charts/options/grid_options.rb +0 -17
  22. data/lib/apex_charts/options/legend_options.rb +0 -29
  23. data/lib/apex_charts/options/markers_options.rb +0 -20
  24. data/lib/apex_charts/options/no_data_options.rb +0 -14
  25. data/lib/apex_charts/options/plot_options.rb +0 -14
  26. data/lib/apex_charts/options/root_options.rb +0 -46
  27. data/lib/apex_charts/options/states_options.rb +0 -11
  28. data/lib/apex_charts/options/stroke_options.rb +0 -14
  29. data/lib/apex_charts/options/theme_options.rb +0 -10
  30. data/lib/apex_charts/options/title_subtitle_options.rb +0 -15
  31. data/lib/apex_charts/options/tooltip_options.rb +0 -24
  32. data/lib/apex_charts/options/x_axis_options.rb +0 -14
  33. data/lib/apex_charts/options/y_axis_options.rb +0 -18
  34. data/lib/apexcharts/prefix_with_apex.rb +0 -20
@@ -1,28 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'smart_kv'
4
- require_relative 'options/root_options'
5
- require_relative 'options/annotations_options'
6
- require_relative 'options/data_labels_options'
7
- require_relative 'options/fill_options'
8
- require_relative 'options/grid_options'
9
- require_relative 'options/legend_options'
10
- require_relative 'options/markers_options'
11
- require_relative 'options/no_data_options'
12
- require_relative 'options/plot_options'
13
- require_relative 'options/states_options'
14
- require_relative 'options/title_subtitle_options'
15
- require_relative 'options/theme_options'
16
- require_relative 'options/tooltip_options'
17
- require_relative 'options/x_axis_options'
18
- require_relative 'options/y_axis_options'
19
-
20
3
  module ApexCharts
21
4
  class OptionsBuilder
22
5
  include ApexCharts::Utils::Hash
23
6
  include ApexCharts::Utils::DateTime
24
7
 
25
- attr_reader :built
8
+ attr_accessor :built
26
9
 
27
10
  def initialize(sample, options)
28
11
  @options = camelize_keys(options)
@@ -35,8 +18,6 @@ module ApexCharts
35
18
  end
36
19
 
37
20
  def build_options
38
- Options::RootOptions.check @options
39
-
40
21
  build_chart
41
22
  build_div
42
23
  build_general_options
@@ -46,11 +27,13 @@ module ApexCharts
46
27
  build_annotations
47
28
  build_colors
48
29
  build_data_labels
30
+ build_defer
49
31
  build_fill
50
32
  build_grid
51
33
  build_labels
52
34
  build_legend
53
35
  build_markers
36
+ build_module
54
37
  build_no_data
55
38
  build_plot_options
56
39
  build_responsive
@@ -66,7 +49,7 @@ module ApexCharts
66
49
  end
67
50
 
68
51
  def build_div
69
- @built[:div] = {
52
+ built[:div] = {
70
53
  id: @options.delete(:id),
71
54
  var: @options.delete(:var),
72
55
  class: @options.delete(:class),
@@ -76,20 +59,23 @@ module ApexCharts
76
59
 
77
60
  def build_annotations
78
61
  annotations = @options.delete :annotations
79
- @built[:annotations] = (
80
- Options::AnnotationsOptions.check annotations.compact if annotations.is_a? Hash
62
+ built[:annotations] = (
63
+ annotations.compact if annotations.is_a? Hash
81
64
  )
82
65
  end
83
66
 
84
67
  def build_chart
85
- @built[:chart] =
68
+ built[:chart] =
86
69
  if target = @options.delete(:brushTarget)
87
- {brush: {enabled: true, target: target.to_s}, selection: {enabled: true}}
70
+ {
71
+ brush: {enabled: true, target: target.to_s},
72
+ selection: {enabled: true}
73
+ }
88
74
  else
89
75
  {}
90
76
  end
91
77
 
92
- @built[:chart].merge!({
78
+ built[:chart].merge!({
93
79
  id: @options[:chartId] || @options[:id],
94
80
  group: @options.delete(:group),
95
81
  height: @options.delete(:height) { target ? 180 : 400 },
@@ -105,203 +91,234 @@ module ApexCharts
105
91
 
106
92
  return unless chart.is_a? Hash
107
93
 
108
- @built[:chart].merge! Options::ChartOptions.check(chart.compact)
94
+ built[:chart].merge! chart.compact
109
95
  end
110
96
 
111
97
  def build_colors
112
98
  colors = @options.delete :colors
113
99
  colors &&= Array(colors)
114
- @built[:colors] = colors
100
+ built[:colors] = colors
115
101
  end
116
102
 
117
103
  def build_data_labels
118
104
  data_labels = @options.delete :dataLabels
119
105
  return if data_labels.nil?
120
106
 
121
- @built[:dataLabels] = if [true, false].include? data_labels
122
- {enabled: data_labels}
123
- elsif data_labels.is_a? Hash
124
- Options::DataLabelsOptions.check data_labels.compact
125
- end
107
+ built[:dataLabels] = if [true, false].include? data_labels
108
+ {enabled: data_labels}
109
+ elsif data_labels.is_a? Hash
110
+ data_labels.compact
111
+ end
112
+ end
113
+
114
+ def build_defer
115
+ defer = @options.delete :defer
116
+ built[:defer] = defer == true
117
+ end
118
+
119
+ def build_module
120
+ omodule = @options.delete :module
121
+ built[:module] = omodule == true
126
122
  end
127
123
 
128
124
  def build_fill
129
125
  fill = @options.delete :fill
130
- @built[:fill] = if fill.is_a? String
131
- {type: fill}
132
- elsif fill.is_a? Hash
133
- Options::FillOptions.check fill.compact
134
- end
126
+ built[:fill] = case fill
127
+ when String
128
+ {type: fill}
129
+ when Hash
130
+ fill.compact
131
+ end
135
132
  end
136
133
 
137
134
  def build_grid
138
135
  grid = @options.delete :grid
139
- @built[:grid] = if [true, false].include? grid
140
- {show: grid}
141
- elsif grid.is_a? Hash
142
- Options::GridOptions.check grid.compact
143
- end
136
+ built[:grid] = if [true, false].include? grid
137
+ {show: grid}
138
+ elsif grid.is_a? Hash
139
+ grid.compact
140
+ end
144
141
  end
145
142
 
146
143
  def build_labels
147
144
  labels = @options.delete :labels
148
145
  labels &&= Array(labels)
149
- @built[:labels] = labels
146
+ built[:labels] = labels
150
147
  end
151
148
 
152
149
  def build_legend
153
150
  legend = @options.delete :legend
154
- @built[:legend] = if [true, false].include? legend
155
- {show: legend}
156
- elsif legend.is_a? String
157
- {show: true, position: legend}
158
- elsif legend.is_a? Hash
159
- Options::LegendOptions.check legend.compact
160
- end
151
+ built[:legend] = if [true, false].include? legend
152
+ {show: legend}
153
+ elsif legend.is_a? String
154
+ {show: true, position: legend}
155
+ elsif legend.is_a? Hash
156
+ legend.compact
157
+ end
161
158
  end
162
159
 
163
160
  def build_markers
164
161
  markers = @options.delete :markers
165
- @built[:markers] = if markers.is_a? String
166
- {shape: markers}
167
- elsif markers.is_a? Hash
168
- Options::MarkersOptions.check markers.compact
169
- end
162
+ built[:markers] = case markers
163
+ when String
164
+ {shape: markers}
165
+ when Hash
166
+ markers.compact
167
+ end
170
168
  end
171
169
 
172
170
  def build_no_data
173
171
  no_data = @options.delete :noData
174
- @built[:noData] = if no_data.is_a? String
175
- {text: no_data}
176
- elsif no_data.is_a? Hash
177
- Options::NoDataOptions.check no_data.compact
178
- end
172
+ built[:noData] = case no_data
173
+ when String
174
+ {text: no_data}
175
+ when Hash
176
+ no_data.compact
177
+ end
179
178
  end
180
179
 
181
180
  def build_plot_options
182
181
  plot_options = @options.delete :plotOptions
183
182
  return unless plot_options.is_a? Hash
184
183
 
185
- @built[:plotOptions] =
186
- Options::PlotOptions.check plot_options.compact
184
+ built[:plotOptions] =
185
+ plot_options.compact
187
186
  end
188
187
 
189
188
  def build_responsive
190
189
  responsive = @options.delete :responsive
191
190
  responsive &&= responsive.is_a?(Hash) ? [responsive] : Array(responsive)
192
- @built[:responsive] = responsive
191
+ built[:responsive] = responsive
193
192
  end
194
193
 
195
194
  def build_states
196
- @built[:states] = {
195
+ built[:states] = {
197
196
  normal: filter_type_hash(@options.delete(:normal)),
198
197
  hover: filter_type_hash(@options.delete(:hover)),
199
198
  active: filter_type_hash(@options.delete(:active))
200
199
  }.compact
201
200
 
202
201
  states = @options.delete :states
203
- @built[:states].merge! Options::StatesOptions.check(states.compact) if states.is_a? Hash
202
+ built[:states].merge! states.compact if states.is_a? Hash
204
203
 
205
- @built[:states] = nil if @built[:states].empty?
204
+ built[:states] = nil if built[:states].empty?
206
205
  end
207
206
 
208
207
  def build_stroke
209
208
  curve = @options.delete :curve
210
- @built[:stroke] = {curve: curve}.compact
209
+ built[:stroke] = {curve: curve}.compact
211
210
 
212
211
  stroke = @options.delete :stroke
213
212
  if [true, false].include? stroke
214
- @built[:stroke].merge!(show: stroke)
213
+ built[:stroke].merge!(show: stroke)
215
214
  elsif stroke.is_a? Hash
216
- @built[:stroke].merge! Options::StrokeOptions.check(stroke.compact)
215
+ built[:stroke].merge! stroke.compact
217
216
  end
218
217
 
219
- @built[:stroke] = nil if @built[:stroke].empty?
218
+ built[:stroke] = nil if built[:stroke].empty?
220
219
  end
221
220
 
222
221
  def build_subtitle
223
222
  subtitle = @options.delete(:subtitle)
224
- @built[:subtitle] = if subtitle.is_a? String
225
- {text: subtitle}
226
- elsif subtitle.is_a? Hash
227
- Options::TitleSubtitleOptions.check subtitle.compact
228
- end
223
+ built[:subtitle] = case subtitle
224
+ when String
225
+ {text: subtitle}
226
+ when Hash
227
+ subtitle.compact
228
+ end
229
229
  end
230
230
 
231
231
  def build_theme
232
232
  theme = @options.delete(:theme)
233
- @built[:theme] = if theme.is_a? String
234
- case theme
235
- when 'random'
236
- resolve_theme(Theme::Local.all_palettes.sample)
237
- when 'monochrome'
238
- {monochrome: {enabled: true}}
239
- else
240
- resolve_theme(theme)
241
- end
242
- elsif theme.is_a? Hash
243
- Options::ThemeOptions.check theme.compact
244
- end
233
+ built[:theme] = case theme
234
+ when String
235
+ case theme
236
+ when 'random'
237
+ resolve_theme(Theme.all_palettes.sample)
238
+ when 'monochrome'
239
+ {monochrome: {enabled: true}}
240
+ else
241
+ resolve_theme(theme)
242
+ end
243
+ when Hash
244
+ theme.compact
245
+ end
245
246
  end
246
247
 
247
248
  def build_title
248
249
  title = @options.delete(:title)
249
- @built[:title] = if title.is_a? String
250
- {text: title}
251
- elsif title.is_a? Hash
252
- Options::TitleSubtitleOptions.check title.compact
253
- end
250
+ built[:title] = case title
251
+ when String
252
+ {text: title}
253
+ when Hash
254
+ title.compact
255
+ end
254
256
  end
255
257
 
256
258
  def build_tooltip
257
259
  tooltip = @options.delete :tooltip
258
- @built[:tooltip] = if [true, false].include? tooltip
259
- {enabled: tooltip}
260
- elsif tooltip.is_a? Hash
261
- Options::TooltipOptions.check tooltip.compact
262
- end
260
+ built[:tooltip] = if [true, false].include? tooltip
261
+ {enabled: tooltip}
262
+ elsif tooltip.is_a? Hash
263
+ tooltip.compact
264
+ end
263
265
  end
264
266
 
265
267
  def build_xaxis
266
268
  xaxis = @options.delete :xaxis
267
- @built[:xaxis] = {
269
+ built[:xaxis] = {
268
270
  type: @options.delete(:xtype) { @xtype },
269
271
  title: {
270
272
  text: @options.delete(:xtitle)
271
273
  }.compact
272
274
  }.compact
273
- @built[:xaxis].delete(:title) if @built[:xaxis][:title].empty?
275
+ built[:xaxis].delete(:title) if built[:xaxis][:title].empty?
274
276
 
275
- if xaxis.is_a? String
276
- @built[:xaxis][:title] = {text: xaxis}
277
- elsif xaxis.is_a? Hash
278
- Options::XAxisOptions.check xaxis
279
- @built[:xaxis].merge! xaxis
277
+ case xaxis
278
+ when String
279
+ built[:xaxis][:title] = {text: xaxis}
280
+ when Hash
281
+ built[:xaxis].merge! xaxis
280
282
  end
281
283
 
282
- @built[:xaxis] = nil if @built[:xaxis].empty?
284
+ built[:xaxis] = nil if built[:xaxis].empty?
283
285
  end
284
286
 
285
287
  def build_yaxis
286
288
  yaxis = @options.delete :yaxis
287
- @built[:yaxis] = [{
288
- type: @options.delete(:ytype) { @ytype },
289
- title: {
290
- text: @options.delete(:ytitle)
289
+
290
+ case yaxis
291
+ when Array
292
+ built[:yaxis] = yaxis
293
+ when Hash
294
+ built[:yaxis] = {
295
+ type: @options.delete(:ytype) { @ytype },
296
+ title: {
297
+ text: @options.delete(:ytitle)
298
+ }.compact
291
299
  }.compact
292
- }.compact]
293
- @built[:yaxis][0].delete(:title) if @built[:yaxis][0][:title].empty?
294
-
295
- if yaxis.is_a? String
296
- @built[:yaxis][0][:title] = {text: yaxis}
297
- elsif yaxis.is_a? Hash
298
- Options::YAxisOptions.check yaxis
299
- @built[:yaxis][0].merge! yaxis
300
+ built[:yaxis].delete(:title) if built[:yaxis][:title].empty?
301
+ built[:yaxis].merge! yaxis
302
+ when String
303
+ built[:yaxis] = {
304
+ type: @options.delete(:ytype) { @ytype },
305
+ title: {
306
+ text: yaxis
307
+ }
308
+ }.compact
309
+ when NilClass
310
+ built[:yaxis] = if ytitle = @options.delete(:ytitle)
311
+ {title: {text: ytitle}}
312
+ else
313
+ {}
314
+ end
300
315
  end
301
316
 
302
- @built[:yaxis] = nil if @built[:yaxis].all?(&:empty?)
317
+ built[:yaxis] = nil if built[:yaxis].all?(&:empty?)
303
318
  end
304
319
 
320
+ private
321
+
305
322
  def enabled(options)
306
323
  boolean_to_hash(options) do |opts|
307
324
  {enabled: opts}
@@ -319,9 +336,10 @@ module ApexCharts
319
336
  end
320
337
 
321
338
  def filter_type_hash(state)
322
- if state.is_a? String
339
+ case state
340
+ when String
323
341
  {filter: {type: state}}
324
- elsif state.is_a? Hash
342
+ when Hash
325
343
  state.compact
326
344
  end
327
345
  end
@@ -329,10 +347,15 @@ module ApexCharts
329
347
  def resolve_theme(theme)
330
348
  if Theme::PALETTES.include? theme
331
349
  {palette: theme}
332
- elsif Theme::Local.palette_names.include? theme
333
- @built[:colors] = Theme::Local.get_colors(theme)
350
+ elsif Theme.palette_names.include? theme
351
+ built[:colors] = Theme.get_colors(theme)
334
352
  nil
335
353
  end
336
354
  end
355
+
356
+ def options_class(name)
357
+ schema = ApexCharts.config.schema
358
+ ApexCharts.const_get "Options::#{schema}::#{name}Options"
359
+ end
337
360
  end
338
361
  end
@@ -1,31 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require_relative 'version'
4
5
 
5
6
  module ApexCharts
6
7
  class Renderer
7
8
  class << self
8
- def render_default(options)
9
- renderer = new options
10
-
11
- html = if renderer.id_number == '1' && !ApexCharts.config.default_options.empty?
12
- renderer.window_apex
13
- else
14
- ''
15
- end
16
- html + <<~HTML
17
- <div id="#{renderer.element_id}" class="#{renderer.css_class}" style="#{renderer.style}"></div>
18
- <script type="text/javascript">
19
- var #{renderer.variable} = new ApexCharts(document.querySelector("##{renderer.element_id}"), #{substitute_function_object(renderer.options.to_json)});
20
- #{renderer.variable}.render();
21
- </script>
22
- HTML
23
- end
24
-
25
- def substitute_function_object(json)
26
- json.gsub(%r[{"function":{"args":"(?<args>.*?)","body":"(?<body>.*?)"}}]) do
27
- "function(#{$~&.[](:args)}){#{$~&.[](:body)}}"
28
- end
9
+ def render(options)
10
+ new(options).render
29
11
  end
30
12
  end
31
13
 
@@ -35,6 +17,57 @@ module ApexCharts
35
17
  @options = options
36
18
  end
37
19
 
20
+ def render
21
+ html = ''
22
+ html = window_apex if id_number == '1' && !ApexCharts.config.default_options.empty?
23
+
24
+ chart_rendering = <<~JS
25
+ var #{variable} = new ApexCharts(document.querySelector("##{element_id}"), #{substitute_function_object(options.to_json)});
26
+ #{variable}.render();
27
+ JS
28
+
29
+ html += <<~HTML
30
+ <div id="#{element_id}" class="#{css_class}" style="#{style}"></div>
31
+ #{script(defer(chart_rendering))}
32
+ HTML
33
+ end
34
+
35
+ def defer(js)
36
+ if defer?
37
+ <<~DEFERRED
38
+ (function() {
39
+ var createChart = function() {
40
+ #{indent(js)}
41
+ };
42
+ if (window.addEventListener) {
43
+ window.addEventListener("load", createChart, true);
44
+ } else if (window.attachEvent) {
45
+ window.attachEvent("onload", createChart);
46
+ } else {
47
+ createChart();
48
+ }
49
+ })();
50
+ DEFERRED
51
+ else
52
+ js
53
+ end
54
+ end
55
+
56
+ def substitute_function_object(json)
57
+ json.gsub(/{"function":{"args":"(?<args>.*?)","body":"(?<body>.*?)"}}/) do
58
+ body = "\"#{$LAST_MATCH_INFO&.[](:body)}\"".undump
59
+ "function(#{$LAST_MATCH_INFO&.[](:args)}){#{body}}"
60
+ end
61
+ end
62
+
63
+ def defer?
64
+ @defer ||= options.delete(:defer)
65
+ end
66
+
67
+ def module?
68
+ @module ||= options.delete(:module)
69
+ end
70
+
38
71
  def attributes
39
72
  @attributes ||= options.delete(:div) { {} }
40
73
  end
@@ -64,11 +97,22 @@ module ApexCharts
64
97
  end
65
98
 
66
99
  def window_apex
67
- <<~HTML
68
- <script type="text/javascript">
69
- window.Apex = #{ApexCharts.config.default_options.to_json}
100
+ script("window.Apex = #{ApexCharts.config.default_options.to_json}")
101
+ end
102
+
103
+ def script(js)
104
+ type = module? ? 'module' : 'text/javascript'
105
+ <<~SCRIPT
106
+ <script type="#{type}" apexcharts-rb="#{RELEASE}" >
107
+ #{js}
70
108
  </script>
71
- HTML
109
+ SCRIPT
110
+ end
111
+
112
+ def indent(content, times=2)
113
+ content.lines.map.with_index do |line, index|
114
+ (index.zero? ? '' : ' ' * times) + line
115
+ end.join
72
116
  end
73
117
  end
74
118
  end
@@ -20,9 +20,8 @@ module ApexCharts::Series
20
20
  end
21
21
 
22
22
  when Hash
23
- if data_value = data[:data]
24
- [data] if array_of_threes?(data_value)
25
- end
23
+ data_value = data[:data]
24
+ [data] if data_value && array_of_threes?(data_value)
26
25
 
27
26
  end
28
27
 
@@ -15,7 +15,8 @@ module ApexCharts::Series
15
15
  def sample
16
16
  return if empty?
17
17
 
18
- sanitized[:series][0][:data][0][:x]
18
+ first_data = sanitized[:series][0][:data][0]
19
+ first_data.is_a?(Hash) ? first_data[:x] : first_data
19
20
  end
20
21
 
21
22
  private
@@ -75,7 +76,12 @@ module ApexCharts::Series
75
76
  end
76
77
 
77
78
  def array_of_array_to_array_of_xy(data)
78
- data.map {|d| {x: d.first, y: d.last} }
79
+ case data.first
80
+ when Array
81
+ data.map {|d| {x: d.first, y: d.last} }
82
+ else
83
+ data
84
+ end
79
85
  end
80
86
  end
81
87
  end
@@ -39,22 +39,6 @@ module ApexCharts
39
39
  end
40
40
  end
41
41
 
42
- class Local
43
- module LocalClassMethods
44
- include ClassMethods
45
-
46
- def custom_palettes
47
- Theme.palettes.merge(super)
48
- end
49
-
50
- def palettes
51
- Thread.current[:_ApexCharts_Palettes_] ||= {}
52
- end
53
- end
54
-
55
- extend LocalClassMethods
56
- end
57
-
58
42
  extend ClassMethods
59
43
  end
60
44
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApexCharts
4
- VERSION = '0.1.9'
4
+ VERSION = '0.2.0'
5
+ RELEASE = '0.2.0'
5
6
  end