apexcharts 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +149 -56
- data/lib/apex_charts/charts/base_chart.rb +1 -1
- data/lib/apex_charts/charts/box_plot_chart.rb +9 -0
- data/lib/apex_charts/charts.rb +1 -0
- data/lib/apex_charts/helper.rb +9 -8
- data/lib/apex_charts/options_builder.rb +146 -123
- data/lib/apex_charts/renderer.rb +69 -25
- data/lib/apex_charts/series/bubble_series.rb +2 -3
- data/lib/apex_charts/series/cartesian_series.rb +8 -2
- data/lib/apex_charts/theme.rb +0 -16
- data/lib/apex_charts/version.rb +2 -1
- data/vendor/assets/javascripts/apexcharts.js +5 -5
- metadata +4 -51
- data/lib/apex_charts/options/annotations_options.rb +0 -12
- data/lib/apex_charts/options/axis_options.rb +0 -19
- data/lib/apex_charts/options/chart_options.rb +0 -28
- data/lib/apex_charts/options/data_labels_options.rb +0 -16
- data/lib/apex_charts/options/div_attributes.rb +0 -11
- data/lib/apex_charts/options/fill_options.rb +0 -14
- data/lib/apex_charts/options/grid_options.rb +0 -17
- data/lib/apex_charts/options/legend_options.rb +0 -29
- data/lib/apex_charts/options/markers_options.rb +0 -20
- data/lib/apex_charts/options/no_data_options.rb +0 -14
- data/lib/apex_charts/options/plot_options.rb +0 -14
- data/lib/apex_charts/options/root_options.rb +0 -46
- data/lib/apex_charts/options/states_options.rb +0 -11
- data/lib/apex_charts/options/stroke_options.rb +0 -14
- data/lib/apex_charts/options/theme_options.rb +0 -10
- data/lib/apex_charts/options/title_subtitle_options.rb +0 -15
- data/lib/apex_charts/options/tooltip_options.rb +0 -24
- data/lib/apex_charts/options/x_axis_options.rb +0 -14
- data/lib/apex_charts/options/y_axis_options.rb +0 -18
- 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
|
-
|
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
|
-
|
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
|
-
|
80
|
-
|
62
|
+
built[:annotations] = (
|
63
|
+
annotations.compact if annotations.is_a? Hash
|
81
64
|
)
|
82
65
|
end
|
83
66
|
|
84
67
|
def build_chart
|
85
|
-
|
68
|
+
built[:chart] =
|
86
69
|
if target = @options.delete(:brushTarget)
|
87
|
-
{
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
-
|
146
|
+
built[:labels] = labels
|
150
147
|
end
|
151
148
|
|
152
149
|
def build_legend
|
153
150
|
legend = @options.delete :legend
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
186
|
-
|
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
|
-
|
191
|
+
built[:responsive] = responsive
|
193
192
|
end
|
194
193
|
|
195
194
|
def build_states
|
196
|
-
|
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
|
-
|
202
|
+
built[:states].merge! states.compact if states.is_a? Hash
|
204
203
|
|
205
|
-
|
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
|
-
|
209
|
+
built[:stroke] = {curve: curve}.compact
|
211
210
|
|
212
211
|
stroke = @options.delete :stroke
|
213
212
|
if [true, false].include? stroke
|
214
|
-
|
213
|
+
built[:stroke].merge!(show: stroke)
|
215
214
|
elsif stroke.is_a? Hash
|
216
|
-
|
215
|
+
built[:stroke].merge! stroke.compact
|
217
216
|
end
|
218
217
|
|
219
|
-
|
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
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
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
|
-
|
275
|
+
built[:xaxis].delete(:title) if built[:xaxis][:title].empty?
|
274
276
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
-
|
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
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
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
|
-
|
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
|
-
|
339
|
+
case state
|
340
|
+
when String
|
323
341
|
{filter: {type: state}}
|
324
|
-
|
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
|
333
|
-
|
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
|
data/lib/apex_charts/renderer.rb
CHANGED
@@ -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
|
9
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
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
|
@@ -15,7 +15,8 @@ module ApexCharts::Series
|
|
15
15
|
def sample
|
16
16
|
return if empty?
|
17
17
|
|
18
|
-
sanitized[:series][0][:data][0]
|
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.
|
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
|
data/lib/apex_charts/theme.rb
CHANGED
@@ -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
|