apexcharts 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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