blazer 1.7.5 → 1.7.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of blazer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +11 -1
- data/app/assets/javascripts/blazer/chartkick.js +484 -152
- data/app/views/blazer/queries/_form.html.erb +1 -1
- data/app/views/blazer/queries/run.html.erb +3 -1
- data/lib/blazer/adapters/sql_adapter.rb +1 -1
- data/lib/blazer/result.rb +2 -0
- data/lib/blazer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8f87990be2cd7082b9e63283da48848a6815c38
|
4
|
+
data.tar.gz: cdaacc750e40af335e7ce7d32e208f60b5ac9dc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edb80ba4ba8372ac7118ff28b1b3025dcefb13f4ab5a816ce1c6039720b6911bebe4666ea5e7f5e9b190b4cee1ffd00af9f755723cf6c1becaf2e83718f15a1e
|
7
|
+
data.tar.gz: 9625b2373ebcef0a78556a4bbb8613b77e879c4dab9618175e3aadd41c138873e716b26a12df8d3ee4a14ffff0c65269455b9831ec7d8555a154b8a0b43f7997
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -141,7 +141,7 @@ ENV["BLAZER_PASSWORD"] = "secret"
|
|
141
141
|
### Devise
|
142
142
|
|
143
143
|
```ruby
|
144
|
-
authenticate :user,
|
144
|
+
authenticate :user, -> (user) { user.admin? } do
|
145
145
|
mount Blazer::Engine, at: "blazer"
|
146
146
|
end
|
147
147
|
```
|
@@ -260,6 +260,8 @@ Of course, you can force a refresh at any time.
|
|
260
260
|
|
261
261
|
Blazer will automatically generate charts based on the types of the columns returned in your query.
|
262
262
|
|
263
|
+
**Note:** The order of columns matters.
|
264
|
+
|
263
265
|
### Line Chart
|
264
266
|
|
265
267
|
There are two ways to generate line charts.
|
@@ -293,6 +295,14 @@ SELECT gender, COUNT(*) FROM users GROUP BY 1
|
|
293
295
|
SELECT gender, zip_code, COUNT(*) FROM users GROUP BY 1, 2
|
294
296
|
```
|
295
297
|
|
298
|
+
### Scatter Chart
|
299
|
+
|
300
|
+
2 columns - both numeric
|
301
|
+
|
302
|
+
```sql
|
303
|
+
SELECT x, y FROM table
|
304
|
+
```
|
305
|
+
|
296
306
|
### Maps
|
297
307
|
|
298
308
|
Columns named `latitude` and `longitude` or `lat` and `lon` or `lat` and `lng` - [Example](https://blazerme.herokuapp.com/queries/15-map)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
/*
|
2
2
|
* Chartkick.js
|
3
|
-
* Create beautiful
|
3
|
+
* Create beautiful charts with one line of JavaScript
|
4
4
|
* https://github.com/ankane/chartkick.js
|
5
|
-
* v2.
|
5
|
+
* v2.2.1
|
6
6
|
* MIT License
|
7
7
|
*/
|
8
8
|
|
@@ -15,6 +15,7 @@
|
|
15
15
|
var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
|
16
16
|
var DATE_PATTERN = /^(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)$/i;
|
17
17
|
var GoogleChartsAdapter, HighchartsAdapter, ChartjsAdapter;
|
18
|
+
var pendingRequests = [], runningRequests = 0, maxRequests = 4;
|
18
19
|
|
19
20
|
// helpers
|
20
21
|
|
@@ -62,10 +63,10 @@
|
|
62
63
|
function parseISO8601(input) {
|
63
64
|
var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
|
64
65
|
type = Object.prototype.toString.call(input);
|
65
|
-
if (type ===
|
66
|
+
if (type === "[object Date]") {
|
66
67
|
return input;
|
67
68
|
}
|
68
|
-
if (type !==
|
69
|
+
if (type !== "[object String]") {
|
69
70
|
return;
|
70
71
|
}
|
71
72
|
matches = input.match(ISO8601_PATTERN);
|
@@ -83,7 +84,7 @@
|
|
83
84
|
if (matches[17]) {
|
84
85
|
offset += parseInt(matches[17], 10);
|
85
86
|
}
|
86
|
-
offset *= matches[14] ===
|
87
|
+
offset *= matches[14] === "-" ? -1 : 1;
|
87
88
|
result -= offset * 60 * 1000;
|
88
89
|
}
|
89
90
|
return new Date(result);
|
@@ -104,15 +105,18 @@
|
|
104
105
|
return false;
|
105
106
|
}
|
106
107
|
|
107
|
-
function jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle) {
|
108
|
-
return function (
|
108
|
+
function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
|
109
|
+
return function (chart, opts, chartOptions) {
|
110
|
+
var series = chart.data;
|
109
111
|
var options = merge({}, defaultOptions);
|
110
112
|
options = merge(options, chartOptions || {});
|
111
113
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
114
|
+
if (chart.hideLegend || "legend" in opts) {
|
115
|
+
hideLegend(options, opts.legend, chart.hideLegend);
|
116
|
+
}
|
117
|
+
|
118
|
+
if (opts.title) {
|
119
|
+
setTitle(options, opts.title);
|
116
120
|
}
|
117
121
|
|
118
122
|
// min
|
@@ -163,19 +167,61 @@
|
|
163
167
|
element.style.color = "#ff0000";
|
164
168
|
}
|
165
169
|
|
166
|
-
function
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
170
|
+
function pushRequest(element, url, success) {
|
171
|
+
pendingRequests.push([element, url, success]);
|
172
|
+
runNext();
|
173
|
+
}
|
174
|
+
|
175
|
+
function runNext() {
|
176
|
+
if (runningRequests < maxRequests) {
|
177
|
+
var request = pendingRequests.shift()
|
178
|
+
if (request) {
|
179
|
+
runningRequests++;
|
180
|
+
getJSON(request[0], request[1], request[2]);
|
181
|
+
runNext();
|
175
182
|
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
function requestComplete() {
|
187
|
+
runningRequests--;
|
188
|
+
runNext();
|
189
|
+
}
|
190
|
+
|
191
|
+
function getJSON(element, url, success) {
|
192
|
+
ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
|
193
|
+
var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
|
194
|
+
chartError(element, message);
|
176
195
|
});
|
177
196
|
}
|
178
197
|
|
198
|
+
function ajaxCall(url, success, error) {
|
199
|
+
var $ = window.jQuery || window.Zepto || window.$;
|
200
|
+
|
201
|
+
if ($) {
|
202
|
+
$.ajax({
|
203
|
+
dataType: "json",
|
204
|
+
url: url,
|
205
|
+
success: success,
|
206
|
+
error: error,
|
207
|
+
complete: requestComplete
|
208
|
+
});
|
209
|
+
} else {
|
210
|
+
var xhr = new XMLHttpRequest();
|
211
|
+
xhr.open("GET", url, true);
|
212
|
+
xhr.setRequestHeader("Content-Type", "application/json");
|
213
|
+
xhr.onload = function () {
|
214
|
+
requestComplete();
|
215
|
+
if (xhr.status === 200) {
|
216
|
+
success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
|
217
|
+
} else {
|
218
|
+
error(xhr, "error", xhr.statusText);
|
219
|
+
}
|
220
|
+
};
|
221
|
+
xhr.send();
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
179
225
|
function errorCatcher(chart, callback) {
|
180
226
|
try {
|
181
227
|
callback(chart);
|
@@ -185,18 +231,79 @@
|
|
185
231
|
}
|
186
232
|
}
|
187
233
|
|
188
|
-
function fetchDataSource(chart, callback) {
|
189
|
-
if (typeof
|
190
|
-
|
191
|
-
chart.
|
234
|
+
function fetchDataSource(chart, callback, dataSource) {
|
235
|
+
if (typeof dataSource === "string") {
|
236
|
+
pushRequest(chart.element, dataSource, function (data, textStatus, jqXHR) {
|
237
|
+
chart.rawData = data;
|
192
238
|
errorCatcher(chart, callback);
|
193
239
|
});
|
194
240
|
} else {
|
195
|
-
chart.
|
241
|
+
chart.rawData = dataSource;
|
196
242
|
errorCatcher(chart, callback);
|
197
243
|
}
|
198
244
|
}
|
199
245
|
|
246
|
+
function addDownloadButton(chart) {
|
247
|
+
var element = chart.element;
|
248
|
+
var link = document.createElement("a");
|
249
|
+
link.download = chart.options.download === true ? "chart.png" : chart.options.download; // http://caniuse.com/download
|
250
|
+
link.style.position = "absolute";
|
251
|
+
link.style.top = "20px";
|
252
|
+
link.style.right = "20px";
|
253
|
+
link.style.zIndex = 1000;
|
254
|
+
link.style.lineHeight = "20px";
|
255
|
+
link.target = "_blank"; // for safari
|
256
|
+
var image = document.createElement("img");
|
257
|
+
image.alt = "Download";
|
258
|
+
image.style.border = "none";
|
259
|
+
// icon from font-awesome
|
260
|
+
// http://fa2png.io/
|
261
|
+
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
|
262
|
+
link.appendChild(image);
|
263
|
+
element.style.position = "relative";
|
264
|
+
|
265
|
+
chart.downloadAttached = true;
|
266
|
+
|
267
|
+
// mouseenter
|
268
|
+
addEvent(element, "mouseover", function(e) {
|
269
|
+
var related = e.relatedTarget;
|
270
|
+
// check download option again to ensure it wasn't changed
|
271
|
+
if (!related || (related !== this && !childOf(this, related)) && chart.options.download) {
|
272
|
+
link.href = chart.toImage();
|
273
|
+
element.appendChild(link);
|
274
|
+
}
|
275
|
+
});
|
276
|
+
|
277
|
+
// mouseleave
|
278
|
+
addEvent(element, "mouseout", function(e) {
|
279
|
+
var related = e.relatedTarget;
|
280
|
+
if (!related || (related !== this && !childOf(this, related))) {
|
281
|
+
if (link.parentNode) {
|
282
|
+
link.parentNode.removeChild(link);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
});
|
286
|
+
}
|
287
|
+
|
288
|
+
// http://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
|
289
|
+
function addEvent(elem, event, fn) {
|
290
|
+
if (elem.addEventListener) {
|
291
|
+
elem.addEventListener(event, fn, false);
|
292
|
+
} else {
|
293
|
+
elem.attachEvent("on" + event, function() {
|
294
|
+
// set the this pointer same as addEventListener when fn is called
|
295
|
+
return(fn.call(elem, window.event));
|
296
|
+
});
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
// https://gist.github.com/shawnbot/4166283
|
301
|
+
function childOf(p, c) {
|
302
|
+
if (p === c) return false;
|
303
|
+
while (c && c !== p) c = c.parentNode;
|
304
|
+
return c === p;
|
305
|
+
}
|
306
|
+
|
200
307
|
// type conversions
|
201
308
|
|
202
309
|
function toStr(n) {
|
@@ -299,8 +406,25 @@
|
|
299
406
|
}
|
300
407
|
};
|
301
408
|
|
302
|
-
var hideLegend = function (options) {
|
303
|
-
|
409
|
+
var hideLegend = function (options, legend, hideLegend) {
|
410
|
+
if (legend !== undefined) {
|
411
|
+
options.legend.enabled = !!legend;
|
412
|
+
if (legend && legend !== true) {
|
413
|
+
if (legend === "top" || legend === "bottom") {
|
414
|
+
options.legend.verticalAlign = legend;
|
415
|
+
} else {
|
416
|
+
options.legend.layout = "vertical";
|
417
|
+
options.legend.verticalAlign = "middle";
|
418
|
+
options.legend.align = legend;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
} else if (hideLegend) {
|
422
|
+
options.legend.enabled = false;
|
423
|
+
}
|
424
|
+
};
|
425
|
+
|
426
|
+
var setTitle = function (options, title) {
|
427
|
+
options.title.text = title;
|
304
428
|
};
|
305
429
|
|
306
430
|
var setMin = function (options, min) {
|
@@ -323,7 +447,7 @@
|
|
323
447
|
options.yAxis.title.text = title;
|
324
448
|
};
|
325
449
|
|
326
|
-
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
|
450
|
+
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
327
451
|
|
328
452
|
this.renderLineChart = function (chart, chartType) {
|
329
453
|
chartType = chartType || "spline";
|
@@ -334,6 +458,9 @@
|
|
334
458
|
areaspline: {
|
335
459
|
stacking: "normal"
|
336
460
|
},
|
461
|
+
area: {
|
462
|
+
stacking: "normal"
|
463
|
+
},
|
337
464
|
series: {
|
338
465
|
marker: {
|
339
466
|
enabled: false
|
@@ -342,15 +469,26 @@
|
|
342
469
|
}
|
343
470
|
};
|
344
471
|
}
|
345
|
-
|
346
|
-
|
347
|
-
|
472
|
+
|
473
|
+
if (chart.options.curve === false) {
|
474
|
+
if (chartType === "areaspline") {
|
475
|
+
chartType = "area";
|
476
|
+
} else if (chartType === "spline") {
|
477
|
+
chartType = "line";
|
478
|
+
}
|
479
|
+
}
|
480
|
+
|
481
|
+
var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
|
482
|
+
options.xAxis.type = chart.discrete ? "category" : "datetime";
|
483
|
+
if (!options.chart.type) {
|
484
|
+
options.chart.type = chartType;
|
485
|
+
}
|
348
486
|
options.chart.renderTo = chart.element.id;
|
349
487
|
|
350
488
|
var series = chart.data;
|
351
489
|
for (i = 0; i < series.length; i++) {
|
352
490
|
data = series[i].data;
|
353
|
-
if (!chart.
|
491
|
+
if (!chart.discrete) {
|
354
492
|
for (j = 0; j < data.length; j++) {
|
355
493
|
data[j][0] = data[j][0].getTime();
|
356
494
|
}
|
@@ -358,37 +496,50 @@
|
|
358
496
|
series[i].marker = {symbol: "circle"};
|
359
497
|
}
|
360
498
|
options.series = series;
|
361
|
-
new Highcharts.Chart(options);
|
499
|
+
chart.chart = new Highcharts.Chart(options);
|
362
500
|
};
|
363
501
|
|
364
502
|
this.renderScatterChart = function (chart) {
|
365
503
|
var chartOptions = {};
|
366
|
-
var options = jsOptions(chart
|
367
|
-
options.chart.type =
|
504
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
505
|
+
options.chart.type = "scatter";
|
368
506
|
options.chart.renderTo = chart.element.id;
|
369
507
|
options.series = chart.data;
|
370
|
-
new Highcharts.Chart(options);
|
508
|
+
chart.chart = new Highcharts.Chart(options);
|
371
509
|
};
|
372
510
|
|
373
511
|
this.renderPieChart = function (chart) {
|
374
|
-
var chartOptions = {};
|
512
|
+
var chartOptions = merge(defaultOptions, {});
|
513
|
+
|
375
514
|
if (chart.options.colors) {
|
376
515
|
chartOptions.colors = chart.options.colors;
|
377
516
|
}
|
378
|
-
|
517
|
+
if (chart.options.donut) {
|
518
|
+
chartOptions.plotOptions = {pie: {innerSize: "50%"}};
|
519
|
+
}
|
520
|
+
|
521
|
+
if ("legend" in chart.options) {
|
522
|
+
hideLegend(chartOptions, chart.options.legend);
|
523
|
+
}
|
524
|
+
|
525
|
+
if (chart.options.title) {
|
526
|
+
setTitle(chartOptions, chart.options.title);
|
527
|
+
}
|
528
|
+
|
529
|
+
var options = merge(chartOptions, chart.options.library || {});
|
379
530
|
options.chart.renderTo = chart.element.id;
|
380
531
|
options.series = [{
|
381
532
|
type: "pie",
|
382
533
|
name: chart.options.label || "Value",
|
383
534
|
data: chart.data
|
384
535
|
}];
|
385
|
-
new Highcharts.Chart(options);
|
536
|
+
chart.chart = new Highcharts.Chart(options);
|
386
537
|
};
|
387
538
|
|
388
539
|
this.renderColumnChart = function (chart, chartType) {
|
389
540
|
chartType = chartType || "column";
|
390
541
|
var series = chart.data;
|
391
|
-
var options = jsOptions(
|
542
|
+
var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
|
392
543
|
options.chart.type = chartType;
|
393
544
|
options.chart.renderTo = chart.element.id;
|
394
545
|
|
@@ -399,17 +550,12 @@
|
|
399
550
|
d = s.data[j];
|
400
551
|
if (!rows[d[0]]) {
|
401
552
|
rows[d[0]] = new Array(series.length);
|
553
|
+
categories.push(d[0]);
|
402
554
|
}
|
403
555
|
rows[d[0]][i] = d[1];
|
404
556
|
}
|
405
557
|
}
|
406
558
|
|
407
|
-
var categories = [];
|
408
|
-
for (i in rows) {
|
409
|
-
if (rows.hasOwnProperty(i)) {
|
410
|
-
categories.push(i);
|
411
|
-
}
|
412
|
-
}
|
413
559
|
options.xAxis.categories = categories;
|
414
560
|
|
415
561
|
var newSeries = [];
|
@@ -426,7 +572,7 @@
|
|
426
572
|
}
|
427
573
|
options.series = newSeries;
|
428
574
|
|
429
|
-
new Highcharts.Chart(options);
|
575
|
+
chart.chart = new Highcharts.Chart(options);
|
430
576
|
};
|
431
577
|
|
432
578
|
var self = this;
|
@@ -441,7 +587,7 @@
|
|
441
587
|
};
|
442
588
|
adapters.push(HighchartsAdapter);
|
443
589
|
}
|
444
|
-
if (!GoogleChartsAdapter && window.google && window.google.setOnLoadCallback) {
|
590
|
+
if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
|
445
591
|
GoogleChartsAdapter = new function () {
|
446
592
|
var google = window.google;
|
447
593
|
|
@@ -484,7 +630,12 @@
|
|
484
630
|
if (config.language) {
|
485
631
|
loadOptions.language = config.language;
|
486
632
|
}
|
487
|
-
|
633
|
+
|
634
|
+
if (window.google.setOnLoadCallback) {
|
635
|
+
google.load("visualization", "1", loadOptions);
|
636
|
+
} else {
|
637
|
+
google.charts.load("current", loadOptions);
|
638
|
+
}
|
488
639
|
}
|
489
640
|
};
|
490
641
|
|
@@ -531,8 +682,25 @@
|
|
531
682
|
}
|
532
683
|
};
|
533
684
|
|
534
|
-
var hideLegend = function (options) {
|
535
|
-
|
685
|
+
var hideLegend = function (options, legend, hideLegend) {
|
686
|
+
if (legend !== undefined) {
|
687
|
+
var position;
|
688
|
+
if (!legend) {
|
689
|
+
position = "none";
|
690
|
+
} else if (legend === true) {
|
691
|
+
position = "right";
|
692
|
+
} else {
|
693
|
+
position = legend;
|
694
|
+
}
|
695
|
+
options.legend.position = position;
|
696
|
+
} else if (hideLegend) {
|
697
|
+
options.legend.position = "none";
|
698
|
+
}
|
699
|
+
};
|
700
|
+
|
701
|
+
var setTitle = function (options, title) {
|
702
|
+
options.title = title;
|
703
|
+
options.titleTextStyle = {color: "#333", fontSize: "20px"};
|
536
704
|
};
|
537
705
|
|
538
706
|
var setMin = function (options, min) {
|
@@ -565,11 +733,11 @@
|
|
565
733
|
options.vAxis.titleTextStyle.italic = false;
|
566
734
|
};
|
567
735
|
|
568
|
-
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
|
736
|
+
var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
569
737
|
|
570
738
|
// cant use object as key
|
571
739
|
var createDataTable = function (series, columnType) {
|
572
|
-
var i, j, s, d, key, rows = [];
|
740
|
+
var i, j, s, d, key, rows = [], sortedLabels = [];
|
573
741
|
for (i = 0; i < series.length; i++) {
|
574
742
|
s = series[i];
|
575
743
|
|
@@ -578,6 +746,7 @@
|
|
578
746
|
key = (columnType === "datetime") ? d[0].getTime() : d[0];
|
579
747
|
if (!rows[key]) {
|
580
748
|
rows[key] = new Array(series.length);
|
749
|
+
sortedLabels.push(key);
|
581
750
|
}
|
582
751
|
rows[key][i] = toFloat(d[1]);
|
583
752
|
}
|
@@ -586,18 +755,17 @@
|
|
586
755
|
var rows2 = [];
|
587
756
|
var day = true;
|
588
757
|
var value;
|
589
|
-
for (
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
}
|
599
|
-
rows2.push([value].concat(rows[i]));
|
758
|
+
for (var j = 0; j < sortedLabels.length; j++) {
|
759
|
+
var i = sortedLabels[j];
|
760
|
+
if (columnType === "datetime") {
|
761
|
+
value = new Date(toFloat(i));
|
762
|
+
day = day && isDay(value);
|
763
|
+
} else if (columnType === "number") {
|
764
|
+
value = toFloat(i);
|
765
|
+
} else {
|
766
|
+
value = i;
|
600
767
|
}
|
768
|
+
rows2.push([value].concat(rows[i]));
|
601
769
|
}
|
602
770
|
if (columnType === "datetime") {
|
603
771
|
rows2.sort(sortByTime);
|
@@ -626,8 +794,14 @@
|
|
626
794
|
|
627
795
|
this.renderLineChart = function (chart) {
|
628
796
|
waitForLoaded(function () {
|
629
|
-
var
|
630
|
-
|
797
|
+
var chartOptions = {};
|
798
|
+
|
799
|
+
if (chart.options.curve === false) {
|
800
|
+
chartOptions.curveType = "none";
|
801
|
+
}
|
802
|
+
|
803
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
804
|
+
var data = createDataTable(chart.data, chart.discrete ? "string" : "datetime");
|
631
805
|
chart.chart = new google.visualization.LineChart(chart.element);
|
632
806
|
resize(function () {
|
633
807
|
chart.chart.draw(data, options);
|
@@ -641,11 +815,21 @@
|
|
641
815
|
chartArea: {
|
642
816
|
top: "10%",
|
643
817
|
height: "80%"
|
644
|
-
}
|
818
|
+
},
|
819
|
+
legend: {}
|
645
820
|
};
|
646
821
|
if (chart.options.colors) {
|
647
822
|
chartOptions.colors = chart.options.colors;
|
648
823
|
}
|
824
|
+
if (chart.options.donut) {
|
825
|
+
chartOptions.pieHole = 0.5;
|
826
|
+
}
|
827
|
+
if ("legend" in chart.options) {
|
828
|
+
hideLegend(chartOptions, chart.options.legend);
|
829
|
+
}
|
830
|
+
if (chart.options.title) {
|
831
|
+
setTitle(chartOptions, chart.options.title);
|
832
|
+
}
|
649
833
|
var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
|
650
834
|
|
651
835
|
var data = new google.visualization.DataTable();
|
@@ -662,7 +846,7 @@
|
|
662
846
|
|
663
847
|
this.renderColumnChart = function (chart) {
|
664
848
|
waitForLoaded(function () {
|
665
|
-
var options = jsOptions(chart
|
849
|
+
var options = jsOptions(chart, chart.options);
|
666
850
|
var data = createDataTable(chart.data, "string");
|
667
851
|
chart.chart = new google.visualization.ColumnChart(chart.element);
|
668
852
|
resize(function () {
|
@@ -680,7 +864,7 @@
|
|
680
864
|
}
|
681
865
|
}
|
682
866
|
};
|
683
|
-
var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setStacked)(chart
|
867
|
+
var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
|
684
868
|
var data = createDataTable(chart.data, "string");
|
685
869
|
chart.chart = new google.visualization.BarChart(chart.element);
|
686
870
|
resize(function () {
|
@@ -696,8 +880,8 @@
|
|
696
880
|
pointSize: 0,
|
697
881
|
areaOpacity: 0.5
|
698
882
|
};
|
699
|
-
var options = jsOptions(chart
|
700
|
-
var data = createDataTable(chart.data, chart.
|
883
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
884
|
+
var data = createDataTable(chart.data, chart.discrete ? "string" : "datetime");
|
701
885
|
chart.chart = new google.visualization.AreaChart(chart.element);
|
702
886
|
resize(function () {
|
703
887
|
chart.chart.draw(data, options);
|
@@ -730,7 +914,7 @@
|
|
730
914
|
this.renderScatterChart = function (chart) {
|
731
915
|
waitForLoaded(function () {
|
732
916
|
var chartOptions = {};
|
733
|
-
var options = jsOptions(chart
|
917
|
+
var options = jsOptions(chart, chart.options, chartOptions);
|
734
918
|
var data = createDataTable(chart.data, "number");
|
735
919
|
|
736
920
|
chart.chart = new google.visualization.ScatterChart(chart.element);
|
@@ -777,7 +961,12 @@
|
|
777
961
|
|
778
962
|
var baseOptions = {
|
779
963
|
maintainAspectRatio: false,
|
780
|
-
animation: false
|
964
|
+
animation: false,
|
965
|
+
tooltips: {
|
966
|
+
displayColors: false
|
967
|
+
},
|
968
|
+
legend: {},
|
969
|
+
title: {fontSize: 20, fontColor: "#333"}
|
781
970
|
};
|
782
971
|
|
783
972
|
var defaultOptions = {
|
@@ -808,8 +997,7 @@
|
|
808
997
|
ticks: {}
|
809
998
|
}
|
810
999
|
]
|
811
|
-
}
|
812
|
-
legend: {}
|
1000
|
+
}
|
813
1001
|
};
|
814
1002
|
|
815
1003
|
// http://there4.io/2012/05/02/google-chart-color-list/
|
@@ -819,28 +1007,40 @@
|
|
819
1007
|
"#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#3B3EAC"
|
820
1008
|
];
|
821
1009
|
|
822
|
-
var hideLegend = function (options) {
|
823
|
-
|
1010
|
+
var hideLegend = function (options, legend, hideLegend) {
|
1011
|
+
if (legend !== undefined) {
|
1012
|
+
options.legend.display = !!legend;
|
1013
|
+
if (legend && legend !== true) {
|
1014
|
+
options.legend.position = legend;
|
1015
|
+
}
|
1016
|
+
} else if (hideLegend) {
|
1017
|
+
options.legend.display = false;
|
1018
|
+
}
|
1019
|
+
};
|
1020
|
+
|
1021
|
+
var setTitle = function (options, title) {
|
1022
|
+
options.title.display = true;
|
1023
|
+
options.title.text = title;
|
824
1024
|
};
|
825
1025
|
|
826
1026
|
var setMin = function (options, min) {
|
827
1027
|
if (min !== null) {
|
828
|
-
options.scales.yAxes[0].ticks.min = min;
|
1028
|
+
options.scales.yAxes[0].ticks.min = toFloat(min);
|
829
1029
|
}
|
830
1030
|
};
|
831
1031
|
|
832
1032
|
var setMax = function (options, max) {
|
833
|
-
options.scales.yAxes[0].ticks.max = max;
|
1033
|
+
options.scales.yAxes[0].ticks.max = toFloat(max);
|
834
1034
|
};
|
835
1035
|
|
836
1036
|
var setBarMin = function (options, min) {
|
837
1037
|
if (min !== null) {
|
838
|
-
options.scales.xAxes[0].ticks.min = min;
|
1038
|
+
options.scales.xAxes[0].ticks.min = toFloat(min);
|
839
1039
|
}
|
840
1040
|
};
|
841
1041
|
|
842
1042
|
var setBarMax = function (options, max) {
|
843
|
-
options.scales.xAxes[0].ticks.max = max;
|
1043
|
+
options.scales.xAxes[0].ticks.max = toFloat(max);
|
844
1044
|
};
|
845
1045
|
|
846
1046
|
var setStacked = function (options, stacked) {
|
@@ -859,9 +1059,13 @@
|
|
859
1059
|
};
|
860
1060
|
|
861
1061
|
var drawChart = function(chart, type, data, options) {
|
862
|
-
chart.
|
863
|
-
|
1062
|
+
if (chart.chart) {
|
1063
|
+
chart.chart.destroy();
|
1064
|
+
} else {
|
1065
|
+
chart.element.innerHTML = "<canvas></canvas>";
|
1066
|
+
}
|
864
1067
|
|
1068
|
+
var ctx = chart.element.getElementsByTagName("CANVAS")[0];
|
865
1069
|
chart.chart = new Chart(ctx, {
|
866
1070
|
type: type,
|
867
1071
|
data: data,
|
@@ -890,7 +1094,7 @@
|
|
890
1094
|
};
|
891
1095
|
};
|
892
1096
|
|
893
|
-
var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
|
1097
|
+
var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
894
1098
|
|
895
1099
|
var createDataTable = function (chart, options, chartType) {
|
896
1100
|
var datasets = [];
|
@@ -905,7 +1109,7 @@
|
|
905
1109
|
var year = true;
|
906
1110
|
var hour = true;
|
907
1111
|
var minute = true;
|
908
|
-
var detectType = (chartType === "line" || chartType === "area") && !chart.
|
1112
|
+
var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
|
909
1113
|
|
910
1114
|
var series = chart.data;
|
911
1115
|
|
@@ -958,7 +1162,8 @@
|
|
958
1162
|
}
|
959
1163
|
labels.push(value);
|
960
1164
|
for (j = 0; j < series.length; j++) {
|
961
|
-
|
1165
|
+
// Chart.js doesn't like undefined
|
1166
|
+
rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
|
962
1167
|
}
|
963
1168
|
}
|
964
1169
|
|
@@ -977,6 +1182,10 @@
|
|
977
1182
|
borderWidth: 2
|
978
1183
|
};
|
979
1184
|
|
1185
|
+
if (chart.options.curve === false) {
|
1186
|
+
dataset.lineTension = 0;
|
1187
|
+
}
|
1188
|
+
|
980
1189
|
datasets.push(merge(dataset, s.library || {}));
|
981
1190
|
}
|
982
1191
|
|
@@ -1006,7 +1215,8 @@
|
|
1006
1215
|
} else if (day || timeDiff > 10) {
|
1007
1216
|
options.scales.xAxes[0].time.unit = "day";
|
1008
1217
|
step = 1;
|
1009
|
-
} else if (hour) {
|
1218
|
+
} else if (hour || timeDiff > 0.5) {
|
1219
|
+
options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
|
1010
1220
|
options.scales.xAxes[0].time.unit = "hour";
|
1011
1221
|
step = 1 / 24.0;
|
1012
1222
|
} else if (minute) {
|
@@ -1015,7 +1225,6 @@
|
|
1015
1225
|
step = 1 / 24.0 / 60.0;
|
1016
1226
|
}
|
1017
1227
|
|
1018
|
-
|
1019
1228
|
if (step && timeDiff > 0) {
|
1020
1229
|
var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
|
1021
1230
|
if (week && step === 1) {
|
@@ -1045,27 +1254,40 @@
|
|
1045
1254
|
};
|
1046
1255
|
|
1047
1256
|
this.renderLineChart = function (chart, chartType) {
|
1048
|
-
var
|
1257
|
+
var chartOptions = {};
|
1049
1258
|
if (chartType === "area") {
|
1050
1259
|
// TODO fix area stacked
|
1051
|
-
//
|
1260
|
+
// chartOptions.stacked = true;
|
1052
1261
|
}
|
1053
1262
|
// fix for https://github.com/chartjs/Chart.js/issues/2441
|
1054
1263
|
if (!chart.options.max && allZeros(chart.data)) {
|
1055
|
-
|
1264
|
+
chartOptions.max = 1;
|
1056
1265
|
}
|
1057
1266
|
|
1058
|
-
var options = jsOptions(chart
|
1267
|
+
var options = jsOptions(chart, merge(chartOptions, chart.options));
|
1059
1268
|
|
1060
1269
|
var data = createDataTable(chart, options, chartType || "line");
|
1061
1270
|
|
1062
|
-
options.scales.xAxes[0].type = chart.
|
1271
|
+
options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
|
1063
1272
|
|
1064
1273
|
drawChart(chart, "line", data, options);
|
1065
1274
|
};
|
1066
1275
|
|
1067
1276
|
this.renderPieChart = function (chart) {
|
1068
|
-
var options = merge(
|
1277
|
+
var options = merge({}, baseOptions);
|
1278
|
+
if (chart.options.donut) {
|
1279
|
+
options.cutoutPercentage = 50;
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
if ("legend" in chart.options) {
|
1283
|
+
hideLegend(options, chart.options.legend);
|
1284
|
+
}
|
1285
|
+
|
1286
|
+
if (chart.options.title) {
|
1287
|
+
setTitle(options, chart.options.title);
|
1288
|
+
}
|
1289
|
+
|
1290
|
+
options = merge(options, chart.options.library || {});
|
1069
1291
|
|
1070
1292
|
var labels = [];
|
1071
1293
|
var values = [];
|
@@ -1091,9 +1313,9 @@
|
|
1091
1313
|
this.renderColumnChart = function (chart, chartType) {
|
1092
1314
|
var options;
|
1093
1315
|
if (chartType === "bar") {
|
1094
|
-
options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setBarMin, setBarMax, setStacked)(chart
|
1316
|
+
options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
|
1095
1317
|
} else {
|
1096
|
-
options = jsOptions(chart
|
1318
|
+
options = jsOptions(chart, chart.options);
|
1097
1319
|
}
|
1098
1320
|
var data = createDataTable(chart, options, "column");
|
1099
1321
|
setLabelSize(chart, data, options);
|
@@ -1109,15 +1331,57 @@
|
|
1109
1331
|
this.renderBarChart = function (chart) {
|
1110
1332
|
self.renderColumnChart(chart, "bar");
|
1111
1333
|
};
|
1334
|
+
|
1335
|
+
this.renderScatterChart = function (chart) {
|
1336
|
+
var options = jsOptions(chart, chart.options);
|
1337
|
+
|
1338
|
+
var colors = chart.options.colors || defaultColors;
|
1339
|
+
|
1340
|
+
var datasets = [];
|
1341
|
+
var series = chart.data;
|
1342
|
+
for (var i = 0; i < series.length; i++) {
|
1343
|
+
var s = series[i];
|
1344
|
+
var d = [];
|
1345
|
+
for (var j = 0; j < s.data.length; j++) {
|
1346
|
+
d.push({
|
1347
|
+
x: toFloat(s.data[j][0]),
|
1348
|
+
y: toFloat(s.data[j][1])
|
1349
|
+
});
|
1350
|
+
}
|
1351
|
+
|
1352
|
+
datasets.push({
|
1353
|
+
label: s.name,
|
1354
|
+
showLine: false,
|
1355
|
+
data: d,
|
1356
|
+
borderColor: colors[i],
|
1357
|
+
backgroundColor: colors[i],
|
1358
|
+
pointBackgroundColor: colors[i]
|
1359
|
+
})
|
1360
|
+
}
|
1361
|
+
|
1362
|
+
var data = {datasets: datasets};
|
1363
|
+
|
1364
|
+
options.scales.xAxes[0].type = "linear";
|
1365
|
+
options.scales.xAxes[0].position = "bottom";
|
1366
|
+
|
1367
|
+
drawChart(chart, "line", data, options);
|
1368
|
+
};
|
1112
1369
|
};
|
1113
1370
|
|
1114
1371
|
adapters.unshift(ChartjsAdapter);
|
1115
1372
|
}
|
1116
1373
|
}
|
1117
1374
|
|
1375
|
+
function renderChart(chartType, chart) {
|
1376
|
+
callAdapter(chartType, chart);
|
1377
|
+
if (chart.options.download && !chart.downloadAttached && chart.adapter === "chartjs") {
|
1378
|
+
addDownloadButton(chart);
|
1379
|
+
}
|
1380
|
+
}
|
1381
|
+
|
1118
1382
|
// TODO remove chartType if cross-browser way
|
1119
1383
|
// to get the name of the chart class
|
1120
|
-
function
|
1384
|
+
function callAdapter(chartType, chart) {
|
1121
1385
|
var i, adapter, fnName, adapterName;
|
1122
1386
|
fnName = "render" + chartType;
|
1123
1387
|
adapterName = chart.options.adapter;
|
@@ -1127,6 +1391,7 @@
|
|
1127
1391
|
for (i = 0; i < adapters.length; i++) {
|
1128
1392
|
adapter = adapters[i];
|
1129
1393
|
if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
|
1394
|
+
chart.adapter = adapter.name;
|
1130
1395
|
return adapter[fnName](chart);
|
1131
1396
|
}
|
1132
1397
|
}
|
@@ -1212,20 +1477,25 @@
|
|
1212
1477
|
return false;
|
1213
1478
|
}
|
1214
1479
|
|
1215
|
-
function processSeries(
|
1480
|
+
function processSeries(chart, keyType) {
|
1216
1481
|
var i;
|
1217
1482
|
|
1483
|
+
var opts = chart.options;
|
1484
|
+
var series = chart.rawData;
|
1485
|
+
|
1218
1486
|
// see if one series or multiple
|
1219
1487
|
if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
|
1220
1488
|
series = [{name: opts.label || "Value", data: series}];
|
1221
|
-
|
1489
|
+
chart.hideLegend = true;
|
1222
1490
|
} else {
|
1223
|
-
|
1491
|
+
chart.hideLegend = false;
|
1224
1492
|
}
|
1225
1493
|
if ((opts.discrete === null || opts.discrete === undefined)) {
|
1226
|
-
|
1494
|
+
chart.discrete = detectDiscrete(series);
|
1495
|
+
} else {
|
1496
|
+
chart.discrete = opts.discrete;
|
1227
1497
|
}
|
1228
|
-
if (
|
1498
|
+
if (chart.discrete) {
|
1229
1499
|
keyType = "string";
|
1230
1500
|
}
|
1231
1501
|
|
@@ -1237,17 +1507,17 @@
|
|
1237
1507
|
return series;
|
1238
1508
|
}
|
1239
1509
|
|
1240
|
-
function processSimple(
|
1241
|
-
var perfectData = toArr(
|
1510
|
+
function processSimple(chart) {
|
1511
|
+
var perfectData = toArr(chart.rawData), i;
|
1242
1512
|
for (i = 0; i < perfectData.length; i++) {
|
1243
1513
|
perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
|
1244
1514
|
}
|
1245
1515
|
return perfectData;
|
1246
1516
|
}
|
1247
1517
|
|
1248
|
-
function processTime(
|
1518
|
+
function processTime(chart)
|
1249
1519
|
{
|
1250
|
-
var i;
|
1520
|
+
var i, data = chart.rawData;
|
1251
1521
|
for (i = 0; i < data.length; i++) {
|
1252
1522
|
data[i][1] = toDate(data[i][1]);
|
1253
1523
|
data[i][2] = toDate(data[i][2]);
|
@@ -1256,46 +1526,26 @@
|
|
1256
1526
|
}
|
1257
1527
|
|
1258
1528
|
function processLineData(chart) {
|
1259
|
-
|
1260
|
-
renderChart("LineChart", chart);
|
1529
|
+
return processSeries(chart, "datetime");
|
1261
1530
|
}
|
1262
1531
|
|
1263
1532
|
function processColumnData(chart) {
|
1264
|
-
|
1265
|
-
renderChart("ColumnChart", chart);
|
1266
|
-
}
|
1267
|
-
|
1268
|
-
function processPieData(chart) {
|
1269
|
-
chart.data = processSimple(chart.data);
|
1270
|
-
renderChart("PieChart", chart);
|
1533
|
+
return processSeries(chart, "string");
|
1271
1534
|
}
|
1272
1535
|
|
1273
1536
|
function processBarData(chart) {
|
1274
|
-
|
1275
|
-
renderChart("BarChart", chart);
|
1537
|
+
return processSeries(chart, "string");
|
1276
1538
|
}
|
1277
1539
|
|
1278
1540
|
function processAreaData(chart) {
|
1279
|
-
|
1280
|
-
renderChart("AreaChart", chart);
|
1281
|
-
}
|
1282
|
-
|
1283
|
-
function processGeoData(chart) {
|
1284
|
-
chart.data = processSimple(chart.data);
|
1285
|
-
renderChart("GeoChart", chart);
|
1541
|
+
return processSeries(chart, "datetime");
|
1286
1542
|
}
|
1287
1543
|
|
1288
1544
|
function processScatterData(chart) {
|
1289
|
-
|
1290
|
-
renderChart("ScatterChart", chart);
|
1291
|
-
}
|
1292
|
-
|
1293
|
-
function processTimelineData(chart) {
|
1294
|
-
chart.data = processTime(chart.data);
|
1295
|
-
renderChart("Timeline", chart);
|
1545
|
+
return processSeries(chart, "number");
|
1296
1546
|
}
|
1297
1547
|
|
1298
|
-
function
|
1548
|
+
function createChart(chartType, chart, element, dataSource, opts, processData) {
|
1299
1549
|
var elementId;
|
1300
1550
|
if (typeof element === "string") {
|
1301
1551
|
elementId = element;
|
@@ -1304,53 +1554,135 @@
|
|
1304
1554
|
throw new Error("No element with id " + elementId);
|
1305
1555
|
}
|
1306
1556
|
}
|
1557
|
+
|
1307
1558
|
chart.element = element;
|
1308
|
-
|
1559
|
+
opts = merge(Chartkick.options, opts || {});
|
1560
|
+
chart.options = opts;
|
1309
1561
|
chart.dataSource = dataSource;
|
1562
|
+
|
1563
|
+
if (!processData) {
|
1564
|
+
processData = function (chart) {
|
1565
|
+
return chart.rawData;
|
1566
|
+
}
|
1567
|
+
}
|
1568
|
+
|
1569
|
+
// getters
|
1310
1570
|
chart.getElement = function () {
|
1311
1571
|
return element;
|
1312
1572
|
};
|
1573
|
+
chart.getDataSource = function () {
|
1574
|
+
return chart.dataSource;
|
1575
|
+
};
|
1313
1576
|
chart.getData = function () {
|
1314
1577
|
return chart.data;
|
1315
1578
|
};
|
1316
1579
|
chart.getOptions = function () {
|
1317
|
-
return
|
1580
|
+
return chart.options;
|
1318
1581
|
};
|
1319
1582
|
chart.getChartObject = function () {
|
1320
1583
|
return chart.chart;
|
1321
1584
|
};
|
1585
|
+
chart.getAdapter = function () {
|
1586
|
+
return chart.adapter;
|
1587
|
+
};
|
1588
|
+
|
1589
|
+
var callback = function () {
|
1590
|
+
chart.data = processData(chart);
|
1591
|
+
renderChart(chartType, chart);
|
1592
|
+
};
|
1593
|
+
|
1594
|
+
// functions
|
1595
|
+
chart.updateData = function (dataSource, options) {
|
1596
|
+
chart.dataSource = dataSource;
|
1597
|
+
if (options) {
|
1598
|
+
chart.options = merge(Chartkick.options, options);
|
1599
|
+
}
|
1600
|
+
fetchDataSource(chart, callback, dataSource);
|
1601
|
+
};
|
1602
|
+
chart.setOptions = function (options) {
|
1603
|
+
chart.options = merge(Chartkick.options, options);
|
1604
|
+
chart.redraw();
|
1605
|
+
};
|
1606
|
+
chart.redraw = function() {
|
1607
|
+
fetchDataSource(chart, callback, chart.rawData);
|
1608
|
+
};
|
1609
|
+
chart.refreshData = function () {
|
1610
|
+
if (typeof dataSource === "string") {
|
1611
|
+
// prevent browser from caching
|
1612
|
+
var sep = dataSource.indexOf("?") === -1 ? "?" : "&";
|
1613
|
+
var url = dataSource + sep + "_=" + (new Date()).getTime();
|
1614
|
+
fetchDataSource(chart, callback, url);
|
1615
|
+
}
|
1616
|
+
};
|
1617
|
+
chart.stopRefresh = function () {
|
1618
|
+
if (chart.intervalId) {
|
1619
|
+
clearInterval(chart.intervalId);
|
1620
|
+
}
|
1621
|
+
};
|
1622
|
+
chart.toImage = function () {
|
1623
|
+
if (chart.adapter === "chartjs") {
|
1624
|
+
return chart.chart.toBase64Image();
|
1625
|
+
} else {
|
1626
|
+
return null;
|
1627
|
+
}
|
1628
|
+
}
|
1629
|
+
|
1322
1630
|
Chartkick.charts[element.id] = chart;
|
1323
|
-
|
1631
|
+
|
1632
|
+
fetchDataSource(chart, callback, dataSource);
|
1633
|
+
|
1634
|
+
if (opts.refresh) {
|
1635
|
+
chart.intervalId = setInterval( function () {
|
1636
|
+
chart.refreshData();
|
1637
|
+
}, opts.refresh * 1000);
|
1638
|
+
}
|
1324
1639
|
}
|
1325
1640
|
|
1326
1641
|
// define classes
|
1327
1642
|
|
1328
1643
|
Chartkick = {
|
1329
|
-
LineChart: function (element, dataSource,
|
1330
|
-
|
1644
|
+
LineChart: function (element, dataSource, options) {
|
1645
|
+
createChart("LineChart", this, element, dataSource, options, processLineData);
|
1646
|
+
},
|
1647
|
+
PieChart: function (element, dataSource, options) {
|
1648
|
+
createChart("PieChart", this, element, dataSource, options, processSimple);
|
1331
1649
|
},
|
1332
|
-
|
1333
|
-
|
1650
|
+
ColumnChart: function (element, dataSource, options) {
|
1651
|
+
createChart("ColumnChart", this, element, dataSource, options, processColumnData);
|
1334
1652
|
},
|
1335
|
-
|
1336
|
-
|
1653
|
+
BarChart: function (element, dataSource, options) {
|
1654
|
+
createChart("BarChart", this, element, dataSource, options, processBarData);
|
1337
1655
|
},
|
1338
|
-
|
1339
|
-
|
1656
|
+
AreaChart: function (element, dataSource, options) {
|
1657
|
+
createChart("AreaChart", this, element, dataSource, options, processAreaData);
|
1340
1658
|
},
|
1341
|
-
|
1342
|
-
|
1659
|
+
GeoChart: function (element, dataSource, options) {
|
1660
|
+
createChart("GeoChart", this, element, dataSource, options, processSimple);
|
1343
1661
|
},
|
1344
|
-
|
1345
|
-
|
1662
|
+
ScatterChart: function (element, dataSource, options) {
|
1663
|
+
createChart("ScatterChart", this, element, dataSource, options, processScatterData);
|
1346
1664
|
},
|
1347
|
-
|
1348
|
-
|
1665
|
+
Timeline: function (element, dataSource, options) {
|
1666
|
+
createChart("Timeline", this, element, dataSource, options, processTime);
|
1349
1667
|
},
|
1350
|
-
|
1351
|
-
|
1668
|
+
charts: {},
|
1669
|
+
configure: function (options) {
|
1670
|
+
for (var key in options) {
|
1671
|
+
if (options.hasOwnProperty(key)) {
|
1672
|
+
config[key] = options[key];
|
1673
|
+
}
|
1674
|
+
}
|
1675
|
+
},
|
1676
|
+
eachChart: function (callback) {
|
1677
|
+
for (var chartId in Chartkick.charts) {
|
1678
|
+
if (Chartkick.charts.hasOwnProperty(chartId)) {
|
1679
|
+
callback(Chartkick.charts[chartId]);
|
1680
|
+
}
|
1681
|
+
}
|
1352
1682
|
},
|
1353
|
-
|
1683
|
+
options: {},
|
1684
|
+
adapters: adapters,
|
1685
|
+
createChart: createChart
|
1354
1686
|
};
|
1355
1687
|
|
1356
1688
|
if (typeof module === "object" && typeof module.exports === "object") {
|
@@ -218,7 +218,7 @@
|
|
218
218
|
var $select = $("#table_names").selectize({})
|
219
219
|
var selectize = $select[0].selectize
|
220
220
|
selectize.on("change", function(val) {
|
221
|
-
editor.setValue(previewStatement[_this.dataSource].replace("{table}", val), 1)
|
221
|
+
editor.setValue(previewStatement[_this.dataSource].replace("{table}", '"' + val + '"'), 1)
|
222
222
|
_this.run()
|
223
223
|
selectize.clear(true)
|
224
224
|
selectize.blur()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if @error %>
|
2
|
-
<div class="alert alert-danger"><%= @error %></div>
|
2
|
+
<div class="alert alert-danger"><%= @error.first(200) %></div>
|
3
3
|
<% elsif !@success %>
|
4
4
|
<% if @only_chart %>
|
5
5
|
<p class="text-muted">Select variables</p>
|
@@ -91,6 +91,8 @@
|
|
91
91
|
<% end %>
|
92
92
|
<% end %>
|
93
93
|
<%= column_chart first_20.group_by { |r| v = r[1]; (@boom[@columns[1]] || {})[v.to_s] || v }.each_with_index.map { |(name, v), i| {name: name, data: v.sort_by { |r2| labels.index(r2[0]) }.map { |v2| v3 = v2[0]; [(@boom[@columns[0]] || {})[v3.to_s] || v3, v2[2]] }} }, id: chart_id %>
|
94
|
+
<% elsif chart_type == "scatter" %>
|
95
|
+
<%= scatter_chart @rows, xtitle: @columns[0], ytitle: @columns[1] %>
|
94
96
|
<% elsif @only_chart %>
|
95
97
|
<% if @rows.size == 1 && @rows.first.size == 1 %>
|
96
98
|
<% v = @rows.first.first %>
|
@@ -28,7 +28,7 @@ module Blazer
|
|
28
28
|
columns = result.columns
|
29
29
|
cast_method = Rails::VERSION::MAJOR < 5 ? :type_cast : :cast_value
|
30
30
|
result.rows.each do |untyped_row|
|
31
|
-
rows << (result.column_types.empty? ? untyped_row : columns.each_with_index.map { |c, i| untyped_row[i] ? result.column_types[c].send(cast_method, untyped_row[i]) :
|
31
|
+
rows << (result.column_types.empty? ? untyped_row : columns.each_with_index.map { |c, i| untyped_row[i] ? result.column_types[c].send(cast_method, untyped_row[i]) : untyped_row[i] })
|
32
32
|
end
|
33
33
|
end
|
34
34
|
rescue => e
|
data/lib/blazer/result.rb
CHANGED
data/lib/blazer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|