chart-js-rails 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/lib/chart-js-rails/version.rb +1 -1
- data/vendor/assets/javascripts/Chart.js +350 -197
- metadata +11 -7
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
/*!
|
2
2
|
* Chart.js
|
3
3
|
* http://chartjs.org/
|
4
|
+
* Version: 1.0.1
|
4
5
|
*
|
5
|
-
* Copyright
|
6
|
+
* Copyright 2015 Nick Downie
|
6
7
|
* Released under the MIT license
|
7
8
|
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
|
8
9
|
*/
|
@@ -91,9 +92,15 @@
|
|
91
92
|
// Boolean - whether or not the chart should be responsive and resize when the browser does.
|
92
93
|
responsive: false,
|
93
94
|
|
95
|
+
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
|
96
|
+
maintainAspectRatio: true,
|
97
|
+
|
94
98
|
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
|
95
99
|
showTooltips: true,
|
96
100
|
|
101
|
+
// Boolean - Determines whether to draw built-in tooltip or call custom tooltip function
|
102
|
+
customTooltips: false,
|
103
|
+
|
97
104
|
// Array - Array of string names to attach tooltip events
|
98
105
|
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
|
99
106
|
|
@@ -213,6 +220,41 @@
|
|
213
220
|
return -1;
|
214
221
|
}
|
215
222
|
},
|
223
|
+
where = helpers.where = function(collection, filterCallback){
|
224
|
+
var filtered = [];
|
225
|
+
|
226
|
+
helpers.each(collection, function(item){
|
227
|
+
if (filterCallback(item)){
|
228
|
+
filtered.push(item);
|
229
|
+
}
|
230
|
+
});
|
231
|
+
|
232
|
+
return filtered;
|
233
|
+
},
|
234
|
+
findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
|
235
|
+
// Default to start of the array
|
236
|
+
if (!startIndex){
|
237
|
+
startIndex = -1;
|
238
|
+
}
|
239
|
+
for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
|
240
|
+
var currentItem = arrayToSearch[i];
|
241
|
+
if (filterCallback(currentItem)){
|
242
|
+
return currentItem;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
},
|
246
|
+
findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
|
247
|
+
// Default to end of the array
|
248
|
+
if (!startIndex){
|
249
|
+
startIndex = arrayToSearch.length;
|
250
|
+
}
|
251
|
+
for (var i = startIndex - 1; i >= 0; i--) {
|
252
|
+
var currentItem = arrayToSearch[i];
|
253
|
+
if (filterCallback(currentItem)){
|
254
|
+
return currentItem;
|
255
|
+
}
|
256
|
+
}
|
257
|
+
},
|
216
258
|
inherits = helpers.inherits = function(extensions){
|
217
259
|
//Basic javascript inheritance based on the model created in Backbone.js
|
218
260
|
var parent = this;
|
@@ -241,7 +283,7 @@
|
|
241
283
|
//Method for warning of errors
|
242
284
|
if (window.console && typeof window.console.warn == "function") console.warn(str);
|
243
285
|
},
|
244
|
-
amd = helpers.amd = (typeof
|
286
|
+
amd = helpers.amd = (typeof define == 'function' && define.amd),
|
245
287
|
//-- Math methods
|
246
288
|
isNumber = helpers.isNumber = function(n){
|
247
289
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
@@ -402,6 +444,13 @@
|
|
402
444
|
//Templating methods
|
403
445
|
//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
|
404
446
|
template = helpers.template = function(templateString, valuesObject){
|
447
|
+
|
448
|
+
// If templateString is function rather than string-template - call the function for valuesObject
|
449
|
+
|
450
|
+
if(templateString instanceof Function){
|
451
|
+
return templateString(valuesObject);
|
452
|
+
}
|
453
|
+
|
405
454
|
var cache = {};
|
406
455
|
function tmpl(str, data){
|
407
456
|
// Figure out if we're getting a template, or if we need to
|
@@ -693,16 +742,22 @@
|
|
693
742
|
removeEvent(chartInstance.chart.canvas, eventName, handler);
|
694
743
|
});
|
695
744
|
},
|
696
|
-
|
745
|
+
getMaximumWidth = helpers.getMaximumWidth = function(domNode){
|
697
746
|
var container = domNode.parentNode;
|
698
747
|
// TODO = check cross browser stuff with this.
|
699
748
|
return container.clientWidth;
|
700
749
|
},
|
750
|
+
getMaximumHeight = helpers.getMaximumHeight = function(domNode){
|
751
|
+
var container = domNode.parentNode;
|
752
|
+
// TODO = check cross browser stuff with this.
|
753
|
+
return container.clientHeight;
|
754
|
+
},
|
755
|
+
getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
|
701
756
|
retinaScale = helpers.retinaScale = function(chart){
|
702
757
|
var ctx = chart.ctx,
|
703
758
|
width = chart.canvas.width,
|
704
759
|
height = chart.canvas.height;
|
705
|
-
|
760
|
+
|
706
761
|
if (window.devicePixelRatio) {
|
707
762
|
ctx.canvas.style.width = width + "px";
|
708
763
|
ctx.canvas.style.height = height + "px";
|
@@ -776,11 +831,11 @@
|
|
776
831
|
resize : function(callback){
|
777
832
|
this.stop();
|
778
833
|
var canvas = this.chart.canvas,
|
779
|
-
newWidth =
|
780
|
-
newHeight = newWidth / this.chart.aspectRatio;
|
834
|
+
newWidth = getMaximumWidth(this.chart.canvas),
|
835
|
+
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
|
781
836
|
|
782
837
|
canvas.width = this.chart.width = newWidth;
|
783
|
-
canvas.height =
|
838
|
+
canvas.height = this.chart.height = newHeight;
|
784
839
|
|
785
840
|
retinaScale(this.chart);
|
786
841
|
|
@@ -816,6 +871,21 @@
|
|
816
871
|
destroy : function(){
|
817
872
|
this.clear();
|
818
873
|
unbindEvents(this, this.events);
|
874
|
+
var canvas = this.chart.canvas;
|
875
|
+
|
876
|
+
// Reset canvas height/width attributes starts a fresh with the canvas context
|
877
|
+
canvas.width = this.chart.width;
|
878
|
+
canvas.height = this.chart.height;
|
879
|
+
|
880
|
+
// < IE9 doesn't support removeProperty
|
881
|
+
if (canvas.style.removeProperty) {
|
882
|
+
canvas.style.removeProperty('width');
|
883
|
+
canvas.style.removeProperty('height');
|
884
|
+
} else {
|
885
|
+
canvas.style.removeAttribute('width');
|
886
|
+
canvas.style.removeAttribute('height');
|
887
|
+
}
|
888
|
+
|
819
889
|
delete Chart.instances[this.id];
|
820
890
|
},
|
821
891
|
showTooltip : function(ChartElements, forceRedraw){
|
@@ -845,6 +915,9 @@
|
|
845
915
|
this.activeElements = ChartElements;
|
846
916
|
}
|
847
917
|
this.draw();
|
918
|
+
if(this.options.customTooltips){
|
919
|
+
this.options.customTooltips(false);
|
920
|
+
}
|
848
921
|
if (ChartElements.length > 0){
|
849
922
|
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
|
850
923
|
if (this.datasets && this.datasets.length > 1) {
|
@@ -873,7 +946,7 @@
|
|
873
946
|
yMin;
|
874
947
|
helpers.each(this.datasets, function(dataset){
|
875
948
|
dataCollection = dataset.points || dataset.bars || dataset.segments;
|
876
|
-
if (dataCollection[dataIndex]){
|
949
|
+
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
|
877
950
|
Elements.push(dataCollection[dataIndex]);
|
878
951
|
}
|
879
952
|
});
|
@@ -925,7 +998,8 @@
|
|
925
998
|
legendColorBackground : this.options.multiTooltipKeyBackground,
|
926
999
|
title: ChartElements[0].label,
|
927
1000
|
chart: this.chart,
|
928
|
-
ctx: this.chart.ctx
|
1001
|
+
ctx: this.chart.ctx,
|
1002
|
+
custom: this.options.customTooltips
|
929
1003
|
}).draw();
|
930
1004
|
|
931
1005
|
} else {
|
@@ -944,7 +1018,8 @@
|
|
944
1018
|
caretHeight: this.options.tooltipCaretSize,
|
945
1019
|
cornerRadius: this.options.tooltipCornerRadius,
|
946
1020
|
text: template(this.options.tooltipTemplate, Element),
|
947
|
-
chart: this.chart
|
1021
|
+
chart: this.chart,
|
1022
|
+
custom: this.options.customTooltips
|
948
1023
|
}).draw();
|
949
1024
|
}, this);
|
950
1025
|
}
|
@@ -1037,6 +1112,9 @@
|
|
1037
1112
|
x : this.x,
|
1038
1113
|
y : this.y
|
1039
1114
|
};
|
1115
|
+
},
|
1116
|
+
hasValue: function(){
|
1117
|
+
return isNumber(this.value);
|
1040
1118
|
}
|
1041
1119
|
});
|
1042
1120
|
|
@@ -1083,6 +1161,7 @@
|
|
1083
1161
|
// ctx.fill();
|
1084
1162
|
|
1085
1163
|
// ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
|
1164
|
+
// ctx.lineTo(this.x, this.y);
|
1086
1165
|
// ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
|
1087
1166
|
// ctx.stroke();
|
1088
1167
|
|
@@ -1196,7 +1275,7 @@
|
|
1196
1275
|
this.yAlign = "above";
|
1197
1276
|
|
1198
1277
|
//Distance between the actual element.y position and the start of the tooltip caret
|
1199
|
-
var caretPadding = 2;
|
1278
|
+
var caretPadding = this.caretPadding = 2;
|
1200
1279
|
|
1201
1280
|
var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
|
1202
1281
|
tooltipRectHeight = this.fontSize + 2*this.yPadding,
|
@@ -1218,47 +1297,53 @@
|
|
1218
1297
|
|
1219
1298
|
ctx.fillStyle = this.fillColor;
|
1220
1299
|
|
1221
|
-
|
1222
|
-
{
|
1223
|
-
|
1224
|
-
//Draw a caret above the x/y
|
1225
|
-
ctx.beginPath();
|
1226
|
-
ctx.moveTo(this.x,this.y - caretPadding);
|
1227
|
-
ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
|
1228
|
-
ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
|
1229
|
-
ctx.closePath();
|
1230
|
-
ctx.fill();
|
1231
|
-
break;
|
1232
|
-
case "below":
|
1233
|
-
tooltipY = this.y + caretPadding + this.caretHeight;
|
1234
|
-
//Draw a caret below the x/y
|
1235
|
-
ctx.beginPath();
|
1236
|
-
ctx.moveTo(this.x, this.y + caretPadding);
|
1237
|
-
ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
|
1238
|
-
ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
|
1239
|
-
ctx.closePath();
|
1240
|
-
ctx.fill();
|
1241
|
-
break;
|
1300
|
+
// Custom Tooltips
|
1301
|
+
if(this.custom){
|
1302
|
+
this.custom(this);
|
1242
1303
|
}
|
1304
|
+
else{
|
1305
|
+
switch(this.yAlign)
|
1306
|
+
{
|
1307
|
+
case "above":
|
1308
|
+
//Draw a caret above the x/y
|
1309
|
+
ctx.beginPath();
|
1310
|
+
ctx.moveTo(this.x,this.y - caretPadding);
|
1311
|
+
ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
|
1312
|
+
ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
|
1313
|
+
ctx.closePath();
|
1314
|
+
ctx.fill();
|
1315
|
+
break;
|
1316
|
+
case "below":
|
1317
|
+
tooltipY = this.y + caretPadding + this.caretHeight;
|
1318
|
+
//Draw a caret below the x/y
|
1319
|
+
ctx.beginPath();
|
1320
|
+
ctx.moveTo(this.x, this.y + caretPadding);
|
1321
|
+
ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
|
1322
|
+
ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
|
1323
|
+
ctx.closePath();
|
1324
|
+
ctx.fill();
|
1325
|
+
break;
|
1326
|
+
}
|
1243
1327
|
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1328
|
+
switch(this.xAlign)
|
1329
|
+
{
|
1330
|
+
case "left":
|
1331
|
+
tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
|
1332
|
+
break;
|
1333
|
+
case "right":
|
1334
|
+
tooltipX = this.x - (this.cornerRadius + this.caretHeight);
|
1335
|
+
break;
|
1336
|
+
}
|
1253
1337
|
|
1254
|
-
|
1338
|
+
drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
|
1255
1339
|
|
1256
|
-
|
1340
|
+
ctx.fill();
|
1257
1341
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1342
|
+
ctx.fillStyle = this.textColor;
|
1343
|
+
ctx.textAlign = "center";
|
1344
|
+
ctx.textBaseline = "middle";
|
1345
|
+
ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
|
1346
|
+
}
|
1262
1347
|
}
|
1263
1348
|
});
|
1264
1349
|
|
@@ -1312,36 +1397,42 @@
|
|
1312
1397
|
|
1313
1398
|
},
|
1314
1399
|
draw : function(){
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1400
|
+
// Custom Tooltips
|
1401
|
+
if(this.custom){
|
1402
|
+
this.custom(this);
|
1403
|
+
}
|
1404
|
+
else{
|
1405
|
+
drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
|
1406
|
+
var ctx = this.ctx;
|
1407
|
+
ctx.fillStyle = this.fillColor;
|
1408
|
+
ctx.fill();
|
1409
|
+
ctx.closePath();
|
1320
1410
|
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1411
|
+
ctx.textAlign = "left";
|
1412
|
+
ctx.textBaseline = "middle";
|
1413
|
+
ctx.fillStyle = this.titleTextColor;
|
1414
|
+
ctx.font = this.titleFont;
|
1325
1415
|
|
1326
|
-
|
1416
|
+
ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
|
1327
1417
|
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1418
|
+
ctx.font = this.font;
|
1419
|
+
helpers.each(this.labels,function(label,index){
|
1420
|
+
ctx.fillStyle = this.textColor;
|
1421
|
+
ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
|
1332
1422
|
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1423
|
+
//A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
|
1424
|
+
//ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
|
1425
|
+
//Instead we'll make a white filled block to put the legendColour palette over.
|
1336
1426
|
|
1337
|
-
|
1338
|
-
|
1427
|
+
ctx.fillStyle = this.legendColorBackground;
|
1428
|
+
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
|
1339
1429
|
|
1340
|
-
|
1341
|
-
|
1430
|
+
ctx.fillStyle = this.legendColors[index].fill;
|
1431
|
+
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
|
1342
1432
|
|
1343
1433
|
|
1344
|
-
|
1434
|
+
},this);
|
1435
|
+
}
|
1345
1436
|
}
|
1346
1437
|
});
|
1347
1438
|
|
@@ -1506,14 +1597,24 @@
|
|
1506
1597
|
ctx.font = this.font;
|
1507
1598
|
each(this.yLabels,function(labelString,index){
|
1508
1599
|
var yLabelCenter = this.endPoint - (yLabelGap * index),
|
1509
|
-
linePositionY = Math.round(yLabelCenter)
|
1600
|
+
linePositionY = Math.round(yLabelCenter),
|
1601
|
+
drawHorizontalLine = this.showHorizontalLines;
|
1510
1602
|
|
1511
1603
|
ctx.textAlign = "right";
|
1512
1604
|
ctx.textBaseline = "middle";
|
1513
1605
|
if (this.showLabels){
|
1514
1606
|
ctx.fillText(labelString,xStart - 10,yLabelCenter);
|
1515
1607
|
}
|
1516
|
-
|
1608
|
+
|
1609
|
+
// This is X axis, so draw it
|
1610
|
+
if (index === 0 && !drawHorizontalLine){
|
1611
|
+
drawHorizontalLine = true;
|
1612
|
+
}
|
1613
|
+
|
1614
|
+
if (drawHorizontalLine){
|
1615
|
+
ctx.beginPath();
|
1616
|
+
}
|
1617
|
+
|
1517
1618
|
if (index > 0){
|
1518
1619
|
// This is a grid line in the centre, so drop that
|
1519
1620
|
ctx.lineWidth = this.gridLineWidth;
|
@@ -1526,10 +1627,12 @@
|
|
1526
1627
|
|
1527
1628
|
linePositionY += helpers.aliasPixel(ctx.lineWidth);
|
1528
1629
|
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1630
|
+
if(drawHorizontalLine){
|
1631
|
+
ctx.moveTo(xStart, linePositionY);
|
1632
|
+
ctx.lineTo(this.width, linePositionY);
|
1633
|
+
ctx.stroke();
|
1634
|
+
ctx.closePath();
|
1635
|
+
}
|
1533
1636
|
|
1534
1637
|
ctx.lineWidth = this.lineWidth;
|
1535
1638
|
ctx.strokeStyle = this.lineColor;
|
@@ -1545,9 +1648,17 @@
|
|
1545
1648
|
var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
|
1546
1649
|
// Check to see if line/bar here and decide where to place the line
|
1547
1650
|
linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
|
1548
|
-
isRotated = (this.xLabelRotation > 0)
|
1651
|
+
isRotated = (this.xLabelRotation > 0),
|
1652
|
+
drawVerticalLine = this.showVerticalLines;
|
1549
1653
|
|
1550
|
-
|
1654
|
+
// This is Y axis, so draw it
|
1655
|
+
if (index === 0 && !drawVerticalLine){
|
1656
|
+
drawVerticalLine = true;
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
if (drawVerticalLine){
|
1660
|
+
ctx.beginPath();
|
1661
|
+
}
|
1551
1662
|
|
1552
1663
|
if (index > 0){
|
1553
1664
|
// This is a grid line in the centre, so drop that
|
@@ -1558,10 +1669,13 @@
|
|
1558
1669
|
ctx.lineWidth = this.lineWidth;
|
1559
1670
|
ctx.strokeStyle = this.lineColor;
|
1560
1671
|
}
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1672
|
+
|
1673
|
+
if (drawVerticalLine){
|
1674
|
+
ctx.moveTo(linePos,this.endPoint);
|
1675
|
+
ctx.lineTo(linePos,this.startPoint - 3);
|
1676
|
+
ctx.stroke();
|
1677
|
+
ctx.closePath();
|
1678
|
+
}
|
1565
1679
|
|
1566
1680
|
|
1567
1681
|
ctx.lineWidth = this.lineWidth;
|
@@ -1887,6 +2001,7 @@
|
|
1887
2001
|
};
|
1888
2002
|
|
1889
2003
|
}).call(this);
|
2004
|
+
|
1890
2005
|
(function(){
|
1891
2006
|
"use strict";
|
1892
2007
|
|
@@ -1908,6 +2023,12 @@
|
|
1908
2023
|
//Number - Width of the grid lines
|
1909
2024
|
scaleGridLineWidth : 1,
|
1910
2025
|
|
2026
|
+
//Boolean - Whether to show horizontal lines (except X axis)
|
2027
|
+
scaleShowHorizontalLines: true,
|
2028
|
+
|
2029
|
+
//Boolean - Whether to show vertical lines (except Y axis)
|
2030
|
+
scaleShowVerticalLines: true,
|
2031
|
+
|
1911
2032
|
//Boolean - If there is a stroke on each bar
|
1912
2033
|
barShowStroke : true,
|
1913
2034
|
|
@@ -1993,18 +2114,16 @@
|
|
1993
2114
|
this.datasets.push(datasetObject);
|
1994
2115
|
|
1995
2116
|
helpers.each(dataset.data,function(dataPoint,index){
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
}));
|
2007
|
-
}
|
2117
|
+
//Add a new point for each piece of data, passing any required data to draw.
|
2118
|
+
datasetObject.bars.push(new this.BarClass({
|
2119
|
+
value : dataPoint,
|
2120
|
+
label : data.labels[index],
|
2121
|
+
datasetLabel: dataset.label,
|
2122
|
+
strokeColor : dataset.strokeColor,
|
2123
|
+
fillColor : dataset.fillColor,
|
2124
|
+
highlightFill : dataset.highlightFill || dataset.fillColor,
|
2125
|
+
highlightStroke : dataset.highlightStroke || dataset.strokeColor
|
2126
|
+
}));
|
2008
2127
|
},this);
|
2009
2128
|
|
2010
2129
|
},this);
|
@@ -2097,6 +2216,8 @@
|
|
2097
2216
|
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
2098
2217
|
lineWidth : this.options.scaleLineWidth,
|
2099
2218
|
lineColor : this.options.scaleLineColor,
|
2219
|
+
showHorizontalLines : this.options.scaleShowHorizontalLines,
|
2220
|
+
showVerticalLines : this.options.scaleShowVerticalLines,
|
2100
2221
|
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
2101
2222
|
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
2102
2223
|
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
|
@@ -2119,19 +2240,17 @@
|
|
2119
2240
|
addData : function(valuesArray,label){
|
2120
2241
|
//Map the values array for each of the datasets
|
2121
2242
|
helpers.each(valuesArray,function(value,datasetIndex){
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
}));
|
2134
|
-
}
|
2243
|
+
//Add a new point for each piece of data, passing any required data to draw.
|
2244
|
+
this.datasets[datasetIndex].bars.push(new this.BarClass({
|
2245
|
+
value : value,
|
2246
|
+
label : label,
|
2247
|
+
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
|
2248
|
+
y: this.scale.endPoint,
|
2249
|
+
width : this.scale.calculateBarWidth(this.datasets.length),
|
2250
|
+
base : this.scale.endPoint,
|
2251
|
+
strokeColor : this.datasets[datasetIndex].strokeColor,
|
2252
|
+
fillColor : this.datasets[datasetIndex].fillColor
|
2253
|
+
}));
|
2135
2254
|
},this);
|
2136
2255
|
|
2137
2256
|
this.scale.addXLabel(label);
|
@@ -2168,13 +2287,15 @@
|
|
2168
2287
|
//Draw all the bars for each dataset
|
2169
2288
|
helpers.each(this.datasets,function(dataset,datasetIndex){
|
2170
2289
|
helpers.each(dataset.bars,function(bar,index){
|
2171
|
-
bar.
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2290
|
+
if (bar.hasValue()){
|
2291
|
+
bar.base = this.scale.endPoint;
|
2292
|
+
//Transition then draw
|
2293
|
+
bar.transition({
|
2294
|
+
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
|
2295
|
+
y : this.scale.calculateY(bar.value),
|
2296
|
+
width : this.scale.calculateBarWidth(this.datasets.length)
|
2297
|
+
}, easingDecimal).draw();
|
2298
|
+
}
|
2178
2299
|
},this);
|
2179
2300
|
|
2180
2301
|
},this);
|
@@ -2183,6 +2304,7 @@
|
|
2183
2304
|
|
2184
2305
|
|
2185
2306
|
}).call(this);
|
2307
|
+
|
2186
2308
|
(function(){
|
2187
2309
|
"use strict";
|
2188
2310
|
|
@@ -2385,6 +2507,12 @@
|
|
2385
2507
|
//Number - Width of the grid lines
|
2386
2508
|
scaleGridLineWidth : 1,
|
2387
2509
|
|
2510
|
+
//Boolean - Whether to show horizontal lines (except X axis)
|
2511
|
+
scaleShowHorizontalLines: true,
|
2512
|
+
|
2513
|
+
//Boolean - Whether to show vertical lines (except Y axis)
|
2514
|
+
scaleShowVerticalLines: true,
|
2515
|
+
|
2388
2516
|
//Boolean - Whether the line is curved between points
|
2389
2517
|
bezierCurve : true,
|
2390
2518
|
|
@@ -2467,19 +2595,16 @@
|
|
2467
2595
|
|
2468
2596
|
|
2469
2597
|
helpers.each(dataset.data,function(dataPoint,index){
|
2470
|
-
//Best way to do this? or in draw sequence...?
|
2471
|
-
if (helpers.isNumber(dataPoint)){
|
2472
2598
|
//Add a new point for each piece of data, passing any required data to draw.
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
}
|
2599
|
+
datasetObject.points.push(new this.PointClass({
|
2600
|
+
value : dataPoint,
|
2601
|
+
label : data.labels[index],
|
2602
|
+
datasetLabel: dataset.label,
|
2603
|
+
strokeColor : dataset.pointStrokeColor,
|
2604
|
+
fillColor : dataset.pointColor,
|
2605
|
+
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
|
2606
|
+
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
|
2607
|
+
}));
|
2483
2608
|
},this);
|
2484
2609
|
|
2485
2610
|
this.buildScale(data.labels);
|
@@ -2562,6 +2687,8 @@
|
|
2562
2687
|
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
2563
2688
|
lineWidth : this.options.scaleLineWidth,
|
2564
2689
|
lineColor : this.options.scaleLineColor,
|
2690
|
+
showHorizontalLines : this.options.scaleShowHorizontalLines,
|
2691
|
+
showVerticalLines : this.options.scaleShowVerticalLines,
|
2565
2692
|
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
2566
2693
|
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
2567
2694
|
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
|
@@ -2586,17 +2713,15 @@
|
|
2586
2713
|
//Map the values array for each of the datasets
|
2587
2714
|
|
2588
2715
|
helpers.each(valuesArray,function(value,datasetIndex){
|
2589
|
-
|
2590
|
-
|
2591
|
-
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
}));
|
2599
|
-
}
|
2716
|
+
//Add a new point for each piece of data, passing any required data to draw.
|
2717
|
+
this.datasets[datasetIndex].points.push(new this.PointClass({
|
2718
|
+
value : value,
|
2719
|
+
label : label,
|
2720
|
+
x: this.scale.calculateX(this.scale.valuesCount+1),
|
2721
|
+
y: this.scale.endPoint,
|
2722
|
+
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
|
2723
|
+
fillColor : this.datasets[datasetIndex].pointColor
|
2724
|
+
}));
|
2600
2725
|
},this);
|
2601
2726
|
|
2602
2727
|
this.scale.addXLabel(label);
|
@@ -2624,37 +2749,64 @@
|
|
2624
2749
|
|
2625
2750
|
var ctx = this.chart.ctx;
|
2626
2751
|
|
2752
|
+
// Some helper methods for getting the next/prev points
|
2753
|
+
var hasValue = function(item){
|
2754
|
+
return item.value !== null;
|
2755
|
+
},
|
2756
|
+
nextPoint = function(point, collection, index){
|
2757
|
+
return helpers.findNextWhere(collection, hasValue, index) || point;
|
2758
|
+
},
|
2759
|
+
previousPoint = function(point, collection, index){
|
2760
|
+
return helpers.findPreviousWhere(collection, hasValue, index) || point;
|
2761
|
+
};
|
2762
|
+
|
2627
2763
|
this.scale.draw(easingDecimal);
|
2628
2764
|
|
2629
2765
|
|
2630
2766
|
helpers.each(this.datasets,function(dataset){
|
2767
|
+
var pointsWithValues = helpers.where(dataset.points, hasValue);
|
2631
2768
|
|
2632
2769
|
//Transition each point first so that the line and point drawing isn't out of sync
|
2633
2770
|
//We can use this extra loop to calculate the control points of this dataset also in this loop
|
2634
2771
|
|
2635
|
-
helpers.each(dataset.points,function(point,index){
|
2636
|
-
point.
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2772
|
+
helpers.each(dataset.points, function(point, index){
|
2773
|
+
if (point.hasValue()){
|
2774
|
+
point.transition({
|
2775
|
+
y : this.scale.calculateY(point.value),
|
2776
|
+
x : this.scale.calculateX(index)
|
2777
|
+
}, easingDecimal);
|
2778
|
+
}
|
2641
2779
|
},this);
|
2642
2780
|
|
2643
2781
|
|
2644
2782
|
// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
|
2645
2783
|
// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
|
2646
2784
|
if (this.options.bezierCurve){
|
2647
|
-
helpers.each(
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2651
|
-
point
|
2785
|
+
helpers.each(pointsWithValues, function(point, index){
|
2786
|
+
var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
|
2787
|
+
point.controlPoints = helpers.splineCurve(
|
2788
|
+
previousPoint(point, pointsWithValues, index),
|
2789
|
+
point,
|
2790
|
+
nextPoint(point, pointsWithValues, index),
|
2791
|
+
tension
|
2792
|
+
);
|
2793
|
+
|
2794
|
+
// Prevent the bezier going outside of the bounds of the graph
|
2795
|
+
|
2796
|
+
// Cap puter bezier handles to the upper/lower scale bounds
|
2797
|
+
if (point.controlPoints.outer.y > this.scale.endPoint){
|
2798
|
+
point.controlPoints.outer.y = this.scale.endPoint;
|
2652
2799
|
}
|
2653
|
-
else if (
|
2654
|
-
point.controlPoints =
|
2800
|
+
else if (point.controlPoints.outer.y < this.scale.startPoint){
|
2801
|
+
point.controlPoints.outer.y = this.scale.startPoint;
|
2655
2802
|
}
|
2656
|
-
|
2657
|
-
|
2803
|
+
|
2804
|
+
// Cap inner bezier handles to the upper/lower scale bounds
|
2805
|
+
if (point.controlPoints.inner.y > this.scale.endPoint){
|
2806
|
+
point.controlPoints.inner.y = this.scale.endPoint;
|
2807
|
+
}
|
2808
|
+
else if (point.controlPoints.inner.y < this.scale.startPoint){
|
2809
|
+
point.controlPoints.inner.y = this.scale.startPoint;
|
2658
2810
|
}
|
2659
2811
|
},this);
|
2660
2812
|
}
|
@@ -2664,12 +2816,18 @@
|
|
2664
2816
|
ctx.lineWidth = this.options.datasetStrokeWidth;
|
2665
2817
|
ctx.strokeStyle = dataset.strokeColor;
|
2666
2818
|
ctx.beginPath();
|
2667
|
-
|
2668
|
-
|
2819
|
+
|
2820
|
+
helpers.each(pointsWithValues, function(point, index){
|
2821
|
+
if (index === 0){
|
2822
|
+
ctx.moveTo(point.x, point.y);
|
2823
|
+
}
|
2824
|
+
else{
|
2669
2825
|
if(this.options.bezierCurve){
|
2826
|
+
var previous = previousPoint(point, pointsWithValues, index);
|
2827
|
+
|
2670
2828
|
ctx.bezierCurveTo(
|
2671
|
-
|
2672
|
-
|
2829
|
+
previous.controlPoints.outer.x,
|
2830
|
+
previous.controlPoints.outer.y,
|
2673
2831
|
point.controlPoints.inner.x,
|
2674
2832
|
point.controlPoints.inner.y,
|
2675
2833
|
point.x,
|
@@ -2679,19 +2837,15 @@
|
|
2679
2837
|
else{
|
2680
2838
|
ctx.lineTo(point.x,point.y);
|
2681
2839
|
}
|
2682
|
-
|
2683
2840
|
}
|
2684
|
-
|
2685
|
-
ctx.moveTo(point.x,point.y);
|
2686
|
-
}
|
2687
|
-
},this);
|
2688
|
-
ctx.stroke();
|
2841
|
+
}, this);
|
2689
2842
|
|
2843
|
+
ctx.stroke();
|
2690
2844
|
|
2691
|
-
if (this.options.datasetFill){
|
2845
|
+
if (this.options.datasetFill && pointsWithValues.length > 0){
|
2692
2846
|
//Round off the line by going to the base of the chart, back to the start, then fill.
|
2693
|
-
ctx.lineTo(
|
2694
|
-
ctx.lineTo(
|
2847
|
+
ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
|
2848
|
+
ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
|
2695
2849
|
ctx.fillStyle = dataset.fillColor;
|
2696
2850
|
ctx.closePath();
|
2697
2851
|
ctx.fill();
|
@@ -2700,16 +2854,16 @@
|
|
2700
2854
|
//Now draw the points over the line
|
2701
2855
|
//A little inefficient double looping, but better than the line
|
2702
2856
|
//lagging behind the point positions
|
2703
|
-
helpers.each(
|
2857
|
+
helpers.each(pointsWithValues,function(point){
|
2704
2858
|
point.draw();
|
2705
2859
|
});
|
2706
|
-
|
2707
2860
|
},this);
|
2708
2861
|
}
|
2709
2862
|
});
|
2710
2863
|
|
2711
2864
|
|
2712
2865
|
}).call(this);
|
2866
|
+
|
2713
2867
|
(function(){
|
2714
2868
|
"use strict";
|
2715
2869
|
|
@@ -3071,25 +3225,22 @@
|
|
3071
3225
|
this.datasets.push(datasetObject);
|
3072
3226
|
|
3073
3227
|
helpers.each(dataset.data,function(dataPoint,index){
|
3074
|
-
//Best way to do this? or in draw sequence...?
|
3075
|
-
if (helpers.isNumber(dataPoint)){
|
3076
3228
|
//Add a new point for each piece of data, passing any required data to draw.
|
3077
|
-
|
3078
|
-
|
3079
|
-
|
3080
|
-
}
|
3081
|
-
datasetObject.points.push(new this.PointClass({
|
3082
|
-
value : dataPoint,
|
3083
|
-
label : data.labels[index],
|
3084
|
-
datasetLabel: dataset.label,
|
3085
|
-
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
|
3086
|
-
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
|
3087
|
-
strokeColor : dataset.pointStrokeColor,
|
3088
|
-
fillColor : dataset.pointColor,
|
3089
|
-
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
|
3090
|
-
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
|
3091
|
-
}));
|
3229
|
+
var pointPosition;
|
3230
|
+
if (!this.scale.animation){
|
3231
|
+
pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
|
3092
3232
|
}
|
3233
|
+
datasetObject.points.push(new this.PointClass({
|
3234
|
+
value : dataPoint,
|
3235
|
+
label : data.labels[index],
|
3236
|
+
datasetLabel: dataset.label,
|
3237
|
+
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
|
3238
|
+
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
|
3239
|
+
strokeColor : dataset.pointStrokeColor,
|
3240
|
+
fillColor : dataset.pointColor,
|
3241
|
+
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
|
3242
|
+
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
|
3243
|
+
}));
|
3093
3244
|
},this);
|
3094
3245
|
|
3095
3246
|
},this);
|
@@ -3204,17 +3355,15 @@
|
|
3204
3355
|
//Map the values array for each of the datasets
|
3205
3356
|
this.scale.valuesCount++;
|
3206
3357
|
helpers.each(valuesArray,function(value,datasetIndex){
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3211
|
-
|
3212
|
-
|
3213
|
-
|
3214
|
-
|
3215
|
-
|
3216
|
-
}));
|
3217
|
-
}
|
3358
|
+
var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
|
3359
|
+
this.datasets[datasetIndex].points.push(new this.PointClass({
|
3360
|
+
value : value,
|
3361
|
+
label : label,
|
3362
|
+
x: pointPosition.x,
|
3363
|
+
y: pointPosition.y,
|
3364
|
+
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
|
3365
|
+
fillColor : this.datasets[datasetIndex].pointColor
|
3366
|
+
}));
|
3218
3367
|
},this);
|
3219
3368
|
|
3220
3369
|
this.scale.labels.push(label);
|
@@ -3261,7 +3410,9 @@
|
|
3261
3410
|
|
3262
3411
|
//Transition each point first so that the line and point drawing isn't out of sync
|
3263
3412
|
helpers.each(dataset.points,function(point,index){
|
3264
|
-
|
3413
|
+
if (point.hasValue()){
|
3414
|
+
point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
|
3415
|
+
}
|
3265
3416
|
},this);
|
3266
3417
|
|
3267
3418
|
|
@@ -3288,7 +3439,9 @@
|
|
3288
3439
|
//A little inefficient double looping, but better than the line
|
3289
3440
|
//lagging behind the point positions
|
3290
3441
|
helpers.each(dataset.points,function(point){
|
3291
|
-
point.
|
3442
|
+
if (point.hasValue()){
|
3443
|
+
point.draw();
|
3444
|
+
}
|
3292
3445
|
});
|
3293
3446
|
|
3294
3447
|
},this);
|
@@ -3301,4 +3454,4 @@
|
|
3301
3454
|
|
3302
3455
|
|
3303
3456
|
|
3304
|
-
}).call(this);
|
3457
|
+
}).call(this);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chart-js-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
default_executable:
|
12
|
+
date: 2015-01-19 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: railties
|
17
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>'
|
@@ -22,7 +21,12 @@ dependencies:
|
|
22
21
|
version: '3.1'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>'
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.1'
|
26
30
|
description: Chart.js for use in Rails asset pipeline
|
27
31
|
email:
|
28
32
|
- walsh1kt@gmail.com
|
@@ -39,7 +43,6 @@ files:
|
|
39
43
|
- lib/chart-js-rails.rb
|
40
44
|
- lib/chart-js-rails/version.rb
|
41
45
|
- vendor/assets/javascripts/Chart.js
|
42
|
-
has_rdoc: true
|
43
46
|
homepage: ''
|
44
47
|
licenses: []
|
45
48
|
post_install_message:
|
@@ -60,8 +63,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
63
|
version: '0'
|
61
64
|
requirements: []
|
62
65
|
rubyforge_project:
|
63
|
-
rubygems_version: 1.
|
66
|
+
rubygems_version: 1.8.25
|
64
67
|
signing_key:
|
65
68
|
specification_version: 3
|
66
69
|
summary: Create HTML5 charts
|
67
70
|
test_files: []
|
71
|
+
has_rdoc:
|