<script type="text/javascript" src="../tests/range_tests.js"></script>
<script type="text/javascript" src="../tests/axis_labels.js"></script>
<script type="text/javascript" src="../tests/multi_csv.js"></script>
+ <script type="text/javascript" src="../tests/to_dom_coords.js"></script>
</head>
<body>
<div id='graph'></div>
" and " + p2 + " with attributes " + toString(attrs));
}
+/**
+ * Checks how many lines of the given color have been drawn.
+ * @return {Integer} The number of lines of the given color.
+ */
+CanvasAssertions.numLinesDrawn = function(proxy, color) {
+ var num_lines = 0;
+ for (var i = 0; i < proxy.calls__.length; i++) {
+ var call = proxy.calls__[i];
+ if (call.name == "lineTo" && call.properties.strokeStyle == color) {
+ num_lines++;
+ }
+ }
+ return num_lines;
+}
+
CanvasAssertions.matchPixels = function(expected, actual) {
// Expect array of two integers. Assuming the values are within one
// integer unit of each other. This should be tightened down by someone
var _origFunc = Dygraph.getContext;
SimpleDrawingTestCase.prototype.setUp = function() {
document.body.innerHTML = "<div id='graph'></div>";
- // Dygraph.getContext = function(canvas) {
- // return new Proxy(_origFunc(canvas));
- // }
+ Dygraph.getContext = function(canvas) {
+ return new Proxy(_origFunc(canvas));
+ }
};
SimpleDrawingTestCase.prototype.tearDown = function() {
var graph = document.getElementById("graph");
var g = new Dygraph(graph, ZERO_TO_FIFTY, opts);
- // var htx = g.hidden_ctx_;
+ var htx = g.hidden_ctx_;
- // CanvasAssertions.assertLineDrawn(htx, [56,300], [475,5.8], {
- // strokeStyle: "#008080",
- // lineWidth: 1
- // });
+ CanvasAssertions.assertLineDrawn(htx, [56,300], [475,5.8], {
+ strokeStyle: "#008080",
+ lineWidth: 1
+ });
}
--- /dev/null
+/**
+ * @fileoverview Test cases for toDomCoords/toDataCoords
+ *
+ * @author danvk@google.com (Dan Vanderkam)
+ */
+
+var ToDomCoordsTestCase = TestCase("to-dom-coords");
+
+var _origFunc = Dygraph.getContext;
+ToDomCoordsTestCase.prototype.setUp = function() {
+ document.body.innerHTML = "<div id='graph'></div>";
+ Dygraph.getContext = function(canvas) {
+ return new Proxy(_origFunc(canvas));
+ }
+};
+
+ToDomCoordsTestCase.prototype.tearDown = function() {
+ Dygraph.getContext = _origFunc;
+};
+
+// Checks that toDomCoords and toDataCoords are inverses of one another.
+ToDomCoordsTestCase.prototype.checkForInverses = function(g) {
+ var x_range = g.xAxisRange();
+ var y_range = g.yAxisRange();
+ for (var i = 0; i <= 10; i++) {
+ var x = x_range[0] + i / 10.0 * (x_range[1] - x_range[0]);
+ for (var j = 0; j <= 10; j++) {
+ var y = y_range[0] + j / 10.0 * (y_range[1] - y_range[0]);
+ assertEquals(x, g.toDataXCoord(g.toDomXCoord(x)));
+ assertEquals(y, g.toDataYCoord(g.toDomYCoord(y)));
+ }
+ }
+}
+
+ToDomCoordsTestCase.prototype.testPlainChart = function() {
+ var opts = {
+ drawXAxis: false,
+ drawYAxis: false,
+ drawXGrid: false,
+ drawYGrid: false,
+ rightGap: 0,
+ valueRange: [0, 100],
+ dateWindow: [0, 100],
+ width: 400,
+ height: 400,
+ colors: ['#ff0000']
+ }
+
+ var graph = document.getElementById("graph");
+ g = new Dygraph(graph, [ [0,0], [100,100] ], opts);
+
+ assertEquals([0, 100], g.toDataCoords(0, 0));
+ assertEquals([0, 0], g.toDataCoords(0, 400));
+ assertEquals([100, 100], g.toDataCoords(400, 0));
+ assertEquals([100, 0], g.toDataCoords(400, 400));
+
+ this.checkForInverses(g);
+
+ var htx = g.hidden_ctx_;
+ assertEquals(1, CanvasAssertions.numLinesDrawn(htx, '#ff0000'));
+}
+
+ToDomCoordsTestCase.prototype.testChartWithAxes = function() {
+ var opts = {
+ drawXAxis: true,
+ xAxisHeight: 50,
+ drawYAxis: true,
+ yAxisLabelWidth: 100,
+ axisTickSize: 0,
+ drawXGrid: false,
+ drawYGrid: false,
+ rightGap: 0,
+ valueRange: [0, 100],
+ dateWindow: [0, 100],
+ width: 500,
+ height: 450,
+ colors: ['#ff0000']
+ }
+
+ var graph = document.getElementById("graph");
+ g = new Dygraph(graph, [ [0,0], [100,100] ], opts);
+
+ assertEquals([0, 100], g.toDataCoords(100, 0));
+ assertEquals([0, 0], g.toDataCoords(100, 400));
+ assertEquals([100, 100], g.toDataCoords(500, 0));
+ assertEquals([100, 0], g.toDataCoords(500, 400));
+
+ this.checkForInverses(g);
+}
+
+ToDomCoordsTestCase.prototype.testChartWithAxesAndLabels = function() {
+ var opts = {
+ drawXAxis: true,
+ xAxisHeight: 50,
+ drawYAxis: true,
+ yAxisLabelWidth: 100,
+ axisTickSize: 0,
+ drawXGrid: false,
+ drawYGrid: false,
+ rightGap: 0,
+ valueRange: [0, 100],
+ dateWindow: [0, 100],
+ width: 500,
+ height: 500,
+ colors: ['#ff0000'],
+ ylabel: 'This is the y-axis',
+ xlabel: 'This is the x-axis',
+ xLabelHeight: 25,
+ title: 'This is the title of the chart',
+ titleHeight: 25
+ }
+
+ var graph = document.getElementById("graph");
+ g = new Dygraph(graph, [ [0,0], [100,100] ], opts);
+
+ assertEquals([0, 100], g.toDataCoords(100, 25));
+ assertEquals([0, 0], g.toDataCoords(100, 425));
+ assertEquals([100, 100], g.toDataCoords(500, 25));
+ assertEquals([100, 0], g.toDataCoords(500, 425));
+
+ this.checkForInverses(g);
+}
area.w = this.width - area.x - this.attr_('rightGap');
area.h = this.height;
if (this.attr_('drawXAxis')) {
- area.h -= this.attr_('axisLabelFontSize') + 2 * this.attr_('axisTickSize');
+ if (this.attr_('xAxisHeight')) {
+ area.h -= this.attr_('xAxisHeight');
+ } else {
+ area.h -= this.attr_('axisLabelFontSize') + 2 * this.attr_('axisTickSize');
+ }
}
// Shrink the drawing area to accomodate additional y-axes.
}
}
+ var isNullOrNaN = function(x) {
+ return (x === null || isNaN(x));
+ };
+
for (var i = 0; i < setCount; i++) {
var setName = setNames[i];
var color = this.colors[setName];
for (var j = 0; j < points.length; j++) {
var point = points[j];
if (point.name == setName) {
- if (!Dygraph.isOK(point.canvasy)) {
+ if (isNullOrNaN(point.canvasy)) {
if (stepPlot && prevX != null) {
// Draw a horizontal line to the start of the missing data
ctx.beginPath();
// A point is "isolated" if it is non-null but both the previous
// and next points are null.
var isIsolated = (!prevX && (j == points.length - 1 ||
- !Dygraph.isOK(points[j+1].canvasy)));
+ isNullOrNaN(points[j+1].canvasy)));
if (prevX === null) {
prevX = point.canvasx;
"type": "integer",
"description": "Width, in pixels, of the x-axis labels."
},
+ "xAxisHeight": {
+ "default": "(null)",
+ "labels": ["Axis display"],
+ "type": "integer",
+ "description": "Height, in pixels, of the x-axis. If not set explicitly, this is computed based on axisLabelFontSize and axisTickSize."
+ },
"showLabelsOnHighlight": {
"default": "true",
"labels": ["Interactive Elements", "Legend"],
},
"panEdgeFraction": {
"default": "null",
- "labels": ["Axis Display", "Interactive Elements"],
+ "labels": ["Axis display", "Interactive Elements"],
"type": "float",
"default": "null",
"description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% pased the edges of the displayed values. null means no bounds."
},
"fillAlpha": {
"default": "0.15",
- "labels": ["Error bars", "Data Series Colors"],
+ "labels": ["Error Bars", "Data Series Colors"],
"type": "float (0.0 - 1.0)",
"description" : "Error bars (or custom bars) for each series are drawn in the same color as the series, but with partial transparency. This sets the transparency. A value of 0.0 means that the error bars will not be drawn, whereas a value of 1.0 means that the error bars will be as dark as the line for the series itself. This can be used to produce chart lines whose thickness varies at each point."
},
var labels = op['labels'];
if (typeof(labels) !== 'object') {
warn('Option "' + k + '" is missing a "labels": [...] option');
+ } else {
for (var i = 0; i < labels.length; i++) {
if (!cats.hasOwnProperty(labels[i])) {
warn('Option "' + k + '" has label "' + labels[i] +