Merge branch 'master' of github.com:danvk/dygraphs
[dygraphs.git] / auto_tests / tests / axis_labels.js
1 /**
2 * @fileoverview Test cases for how axis labels are chosen and formatted.
3 *
4 * @author dan@dygraphs.com (Dan Vanderkam)
5 */
6 var AxisLabelsTestCase = TestCase("axis-labels");
7
8 AxisLabelsTestCase.prototype.setUp = function() {
9 document.body.innerHTML = "<div id='graph'></div>";
10 };
11
12 AxisLabelsTestCase.prototype.tearDown = function() {
13 };
14
15 AxisLabelsTestCase.simpleData =
16 "X,Y,Y2\n" +
17 "0,-1,.5\n" +
18 "1,0,.7\n" +
19 "2,1,.4\n" +
20 "3,0,.98\n";
21
22 AxisLabelsTestCase.prototype.kCloseFloat = 1.0e-10;
23
24 AxisLabelsTestCase.prototype.testMinusOneToOne = function() {
25 var opts = {
26 width: 480,
27 height: 320
28 };
29 var data = "X,Y\n" +
30 "0,-1\n" +
31 "1,0\n" +
32 "2,1\n" +
33 "3,0\n"
34 ;
35
36 var graph = document.getElementById("graph");
37 var g = new Dygraph(graph, data, opts);
38
39 // TODO(danvk): would ['-1.0','-0.5','0.0','0.5','1.0'] be better?
40 assertEquals(['-1','-0.5','0','0.5','1'], Util.getYLabels());
41
42 // Go up to 2
43 data += "4,2\n";
44 g.updateOptions({file: data});
45 assertEquals(['-1','-0.5','0','0.5','1','1.5','2'], Util.getYLabels());
46
47 // Now 10
48 data += "5,10\n";
49 g.updateOptions({file: data});
50 assertEquals(['-2','0','2','4','6','8','10'], Util.getYLabels());
51
52 // Now 100
53 data += "6,100\n";
54 g.updateOptions({file: data});
55 assertEquals(['0','20','40','60','80','100'], Util.getYLabels());
56
57 g.setSelection(0);
58 assertEquals('0: Y: -1', Util.getLegend());
59 };
60
61 AxisLabelsTestCase.prototype.testSmallRangeNearZero = function() {
62 var opts = {
63 drawAxesAtZero: true,
64 width: 480,
65 height: 320
66 };
67 var data = "X,Y\n" +
68 "0,-1\n" +
69 "1,0\n" +
70 "2,1\n" +
71 "3,0\n"
72 ;
73 opts.valueRange = [-0.1, 0.1];
74
75 var graph = document.getElementById("graph");
76 var g = new Dygraph(graph, data, opts);
77 assertEqualsDelta([-0.1, -0.08, -0.06, -0.04, -0.02, 0, 0.02, 0.04, 0.06, 0.08],
78 Util.makeNumbers(Util.getYLabels()), this.kCloseFloat);
79
80 opts.valueRange = [-0.05, 0.05];
81 g.updateOptions(opts);
82 assertEquals([-0.05, -0.04, -0.03, -0.02, -0.01, 0, 0.01, 0.02, 0.03, 0.04],
83 Util.makeNumbers(Util.getYLabels()));
84
85 opts.valueRange = [-0.01, 0.01];
86 g.updateOptions(opts);
87 assertEquals([-0.01, -8.00e-3, -6.00e-3, -4.00e-3, -2.00e-3, 0, 2.00e-3, 4.00e-3, 6.00e-3, 8.00e-3],
88 Util.makeNumbers(Util.getYLabels()));
89
90 g.setSelection(1);
91 assertEquals('1: Y: 0', Util.getLegend());
92 };
93
94 AxisLabelsTestCase.prototype.testSmallRangeAwayFromZero = function() {
95 var opts = {
96 width: 480,
97 height: 320
98 };
99 var data = "X,Y\n" +
100 "0,-1\n" +
101 "1,0\n" +
102 "2,1\n" +
103 "3,0\n"
104 ;
105 var graph = document.getElementById("graph");
106
107 opts.valueRange = [9.9, 10.1];
108 var g = new Dygraph(graph, data, opts);
109 assertEquals(["9.9","9.92","9.94","9.96","9.98","10","10.02","10.04","10.06","10.08"], Util.getYLabels());
110
111 opts.valueRange = [9.99, 10.01];
112 g.updateOptions(opts);
113 // TODO(danvk): this is bad
114 assertEquals(["9.99","9.99","9.99","10","10","10","10","10","10.01","10.01"], Util.getYLabels());
115
116 opts.valueRange = [9.999, 10.001];
117 g.updateOptions(opts);
118 // TODO(danvk): this is even worse!
119 assertEquals(["10","10","10","10","10","10","10","10","10","10"], Util.getYLabels());
120
121 g.setSelection(1);
122 assertEquals('1: Y: 0', Util.getLegend());
123 };
124
125 AxisLabelsTestCase.prototype.testXAxisTimeLabelFormatter = function() {
126 var opts = {
127 width: 480,
128 height: 320
129 };
130 var data = [[5.0,0],[5.1,1],[5.2,2],[5.3,3],[5.4,4],[5.5,5],[5.6,6],[5.7,7],[5.8,8],[5.9,9]];
131 var graph = document.getElementById("graph");
132 var g = new Dygraph(graph, data, opts);
133 g.updateOptions({
134 axes : {
135 x : {
136 axisLabelFormatter : function (totalMinutes) {
137 var hours = Math.floor( totalMinutes / 60);
138 var minutes = Math.floor((totalMinutes - (hours * 60)));
139 var seconds = Math.round((totalMinutes * 60) - (hours * 3600) - (minutes * 60));
140
141 if (hours < 10) hours = "0" + hours;
142 if (minutes < 10) minutes = "0" + minutes;
143 if (seconds < 10) seconds = "0" + seconds;
144
145 return hours + ':' + minutes + ':' + seconds;
146 }
147 }
148 }
149 });
150
151 assertEquals(["00:05:00","00:05:12","00:05:24","00:05:36","00:05:48"], Util.getXLabels());
152
153 // The legend does not use the axisLabelFormatter:
154 g.setSelection(1);
155 assertEquals('5.1: Y1: 1', Util.getLegend());
156 };
157
158 AxisLabelsTestCase.prototype.testAxisLabelFormatter = function () {
159 var opts = {
160 width: 480,
161 height: 320,
162 axes : {
163 x : {
164 axisLabelFormatter : function(x, granularity, opts, dg) {
165 assertEquals('number', typeof(x));
166 assertEquals('number', typeof(granularity));
167 assertEquals('function', typeof(opts));
168 assertEquals('[Dygraph graph]', dg.toString());
169 return 'x' + x;
170 }
171 },
172 y : {
173 axisLabelFormatter : function(y, granularity, opts, dg) {
174 assertEquals('number', typeof(y));
175 assertEquals('number', typeof(granularity));
176 assertEquals('function', typeof(opts));
177 assertEquals('[Dygraph graph]', dg.toString());
178 return 'y' + y;
179 }
180 }
181 },
182 labels: ['x', 'y']
183 };
184 var data = [];
185 for (var i = 0; i < 10; i++) {
186 data.push([i, 2 * i]);
187 }
188 var graph = document.getElementById("graph");
189 var g = new Dygraph(graph, data, opts);
190
191 assertEquals(['x0','x2','x4','x6','x8'], Util.getXLabels());
192 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
193
194 g.setSelection(2);
195 assertEquals("2: y: 4", Util.getLegend());
196 };
197
198 AxisLabelsTestCase.prototype.testDateAxisLabelFormatter = function () {
199 var opts = {
200 width: 480,
201 height: 320,
202 axes : {
203 x : {
204 axisLabelFormatter : function(x, granularity, opts, dg) {
205 assertTrue(Dygraph.isDateLike(x));
206 assertEquals('number', typeof(granularity));
207 assertEquals('function', typeof(opts));
208 assertEquals('[Dygraph graph]', dg.toString());
209 return 'x' + Util.formatDate(x);
210 }
211 },
212 y : {
213 axisLabelFormatter : function(y, granularity, opts, dg) {
214 assertEquals('number', typeof(y));
215 assertEquals('number', typeof(granularity));
216 assertEquals('function', typeof(opts));
217 assertEquals('[Dygraph graph]', dg.toString());
218 return 'y' + y;
219 }
220 }
221 },
222 labels: ['x', 'y']
223 };
224 var data = [];
225 for (var i = 1; i < 10; i++) {
226 data.push([new Date("2011/01/0" + i), 2 * i]);
227 }
228 var graph = document.getElementById("graph");
229 var g = new Dygraph(graph, data, opts);
230
231 assertEquals(["x2011/01/01", "x2011/01/02", "x2011/01/03", "x2011/01/04", "x2011/01/05", "x2011/01/06", "x2011/01/07", "x2011/01/08"], Util.getXLabels());
232 assertEquals(['y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
233
234 g.setSelection(0);
235 assertEquals("2011/01/01: y: 2", Util.getLegend());
236 };
237
238 // This test verifies that when a valueFormatter is set (but not an
239 // axisLabelFormatter), then the valueFormatter is used to format the axis
240 // labels.
241 AxisLabelsTestCase.prototype.testValueFormatter = function () {
242 var opts = {
243 width: 480,
244 height: 320,
245 axes : {
246 x : {
247 valueFormatter: function(x, opts, series_name, dg) {
248 assertEquals('number', typeof(x));
249 assertEquals('function', typeof(opts));
250 assertEquals('string', typeof(series_name));
251 assertEquals('[Dygraph graph]', dg.toString());
252 return 'x' + x;
253 }
254 },
255 y : {
256 valueFormatter: function(y, opts, series_name, dg) {
257 assertEquals('number', typeof(y));
258 assertEquals('function', typeof(opts));
259 assertEquals('string', typeof(series_name));
260 assertEquals('[Dygraph graph]', dg.toString());
261 return 'y' + y;
262 }
263 }
264 },
265 labels: ['x', 'y']
266 };
267 var data = [];
268 for (var i = 0; i < 10; i++) {
269 data.push([i, 2 * i]);
270 }
271 var graph = document.getElementById("graph");
272 var g = new Dygraph(graph, data, opts);
273
274 // the valueFormatter options do not affect the ticks.
275 assertEquals(['0','2','4','6','8'], Util.getXLabels());
276 assertEquals(['0','2','4','6','8','10','12','14','16','18'],
277 Util.getYLabels());
278
279 // they do affect the legend, however.
280 g.setSelection(2);
281 assertEquals("x2: y: y4", Util.getLegend());
282 };
283
284 AxisLabelsTestCase.prototype.testDateValueFormatter = function () {
285 var opts = {
286 width: 480,
287 height: 320,
288 axes : {
289 x : {
290 valueFormatter: function(x, opts, series_name, dg) {
291 assertEquals('number', typeof(x));
292 assertEquals('function', typeof(opts));
293 assertEquals('string', typeof(series_name));
294 assertEquals('[Dygraph graph]', dg.toString());
295 return 'x' + Util.formatDate(x);
296 }
297 },
298 y : {
299 valueFormatter: function(y, opts, series_name, dg) {
300 assertEquals('number', typeof(y));
301 assertEquals('function', typeof(opts));
302 assertEquals('string', typeof(series_name));
303 assertEquals('[Dygraph graph]', dg.toString());
304 return 'y' + y;
305 }
306 }
307 },
308 labels: ['x', 'y']
309 };
310
311 var data = [];
312 for (var i = 1; i < 10; i++) {
313 data.push([new Date("2011/01/0" + i), 2 * i]);
314 }
315 var graph = document.getElementById("graph");
316 var g = new Dygraph(graph, data, opts);
317
318 // valueFormatters do not affect ticks.
319 assertEquals(['01Jan','02Jan','03Jan','04Jan','05Jan','06Jan','07Jan','08Jan'], Util.getXLabels());
320 assertEquals(['2','4','6','8','10','12','14','16','18'], Util.getYLabels());
321
322 // the valueFormatter options also affect the legend.
323 g.setSelection(2);
324 assertEquals('x2011/01/03: y: y6', Util.getLegend());
325 };
326
327 // This test verifies that when both a valueFormatter and an axisLabelFormatter
328 // are specified, the axisLabelFormatter takes precedence.
329 AxisLabelsTestCase.prototype.testAxisLabelFormatterPrecedence = function () {
330 var opts = {
331 width: 480,
332 height: 320,
333 axes : {
334 x : {
335 valueFormatter: function(x) {
336 return 'xvf' + x;
337 },
338 axisLabelFormatter: function(x, granularity) {
339 return 'x' + x;
340 }
341 },
342 y : {
343 valueFormatter: function(y) {
344 return 'yvf' + y;
345 },
346 axisLabelFormatter: function(y) {
347 return 'y' + y;
348 }
349 }
350 },
351 labels: ['x', 'y']
352 };
353 var data = [];
354 for (var i = 0; i < 10; i++) {
355 data.push([i, 2 * i]);
356 }
357 var graph = document.getElementById("graph");
358 var g = new Dygraph(graph, data, opts);
359
360 assertEquals(['x0','x2','x4','x6','x8'], Util.getXLabels());
361 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
362
363 g.setSelection(9);
364 assertEquals("xvf9: y: yvf18", Util.getLegend());
365 };
366
367 // This is the same as the previous test, except that options are added
368 // one-by-one.
369 AxisLabelsTestCase.prototype.testAxisLabelFormatterIncremental = function () {
370 var opts = {
371 width: 480,
372 height: 320,
373 labels: ['x', 'y']
374 };
375 var data = [];
376 for (var i = 0; i < 10; i++) {
377 data.push([i, 2 * i]);
378 }
379 var graph = document.getElementById("graph");
380 var g = new Dygraph(graph, data, opts);
381 g.updateOptions({
382 axes : {
383 x : {
384 valueFormatter: function(x) {
385 return 'xvf' + x;
386 }
387 }
388 }
389 });
390 g.updateOptions({
391 axes : {
392 y : {
393 valueFormatter: function(y) {
394 return 'yvf' + y;
395 }
396 }
397 }
398 });
399 g.updateOptions({
400 axes : {
401 x : {
402 axisLabelFormatter: function(x, granularity) {
403 return 'x' + x;
404 }
405 }
406 }
407 });
408 g.updateOptions({
409 axes : {
410 y : {
411 axisLabelFormatter: function(y) {
412 return 'y' + y;
413 }
414 }
415 }
416 });
417
418 assertEquals(["x0","x2","x4","x6","x8"], Util.getXLabels());
419 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
420
421 g.setSelection(9);
422 assertEquals("xvf9: y: yvf18", Util.getLegend());
423 };
424
425 AxisLabelsTestCase.prototype.testGlobalFormatters = function() {
426 var opts = {
427 width: 480,
428 height: 320,
429 labels: ['x', 'y'],
430 valueFormatter: function(x) {
431 return 'vf' + x;
432 },
433 axisLabelFormatter: function(x) {
434 return 'alf' + x;
435 }
436 };
437 var data = [];
438 for (var i = 0; i < 10; i++) {
439 data.push([i, 2 * i]);
440 }
441 var graph = document.getElementById("graph");
442 var g = new Dygraph(graph, data, opts);
443
444 assertEquals(['alf0','alf2','alf4','alf6','alf8'], Util.getXLabels());
445 assertEquals(['alf0','alf2','alf4','alf6','alf8','alf10','alf12','alf14','alf16','alf18'], Util.getYLabels());
446
447 g.setSelection(9);
448 assertEquals("vf9: y: vf18", Util.getLegend());
449 };
450
451 AxisLabelsTestCase.prototype.testSeriesOrder = function() {
452 var opts = {
453 width: 480,
454 height: 320
455 };
456 var data = "x,00,01,10,11\n" +
457 "0,101,201,301,401\n" +
458 "1,102,202,302,402\n" +
459 "2,103,203,303,403\n" +
460 "3,104,204,304,404\n"
461 ;
462
463 var graph = document.getElementById("graph");
464 var g = new Dygraph(graph, data, opts);
465
466 g.setSelection(2);
467 assertEquals('2: 00: 103 01: 203 10: 303 11: 403', Util.getLegend());
468
469 // Sanity checks for indexFromSetName
470 assertEquals(0, g.indexFromSetName("x"));
471 assertEquals(1, g.indexFromSetName("00"));
472 assertEquals(null, g.indexFromSetName("abcde"));
473
474 // Verify that we get the label list back in the right order
475 assertEquals(["x", "00", "01", "10", "11"], g.getLabels());
476 };
477
478 AxisLabelsTestCase.prototype.testLabelKMB = function() {
479 var data = [];
480 data.push([0,0]);
481 data.push([1,2000]);
482 data.push([2,1000]);
483
484 var g = new Dygraph(
485 document.getElementById("graph"),
486 data,
487 {
488 labels: [ 'X', 'bar' ],
489 axes : {
490 y: {
491 labelsKMB: true
492 }
493 }
494 }
495 );
496
497 assertEquals(["0", "500", "1K", "1.5K", "2K"], Util.getYLabels());
498 };
499
500 AxisLabelsTestCase.prototype.testLabelKMG2 = function() {
501 var data = [];
502 data.push([0,0]);
503 data.push([1,2000]);
504 data.push([2,1000]);
505
506 var g = new Dygraph(
507 document.getElementById("graph"),
508 data,
509 {
510 labels: [ 'X', 'bar' ],
511 axes : {
512 y: {
513 labelsKMG2: true
514 }
515 }
516 }
517 );
518
519 assertEquals(
520 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
521 Util.getYLabels());
522 };
523
524 // Same as testLabelKMG2 but specifies the option at the
525 // top of the option dictionary.
526 AxisLabelsTestCase.prototype.testLabelKMG2_top = function() {
527 var data = [];
528 data.push([0,0]);
529 data.push([1,2000]);
530 data.push([2,1000]);
531
532 var g = new Dygraph(
533 document.getElementById("graph"),
534 data,
535 {
536 labels: [ 'X', 'bar' ],
537 labelsKMG2: true
538 }
539 );
540
541 assertEquals(
542 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
543 Util.getYLabels());
544 };
545
546 /**
547 * Verify that log scale axis range is properly specified.
548 */
549 AxisLabelsTestCase.prototype.testLogScale = function() {
550 var g = new Dygraph("graph", [[0, 5], [1, 1000]], { logscale : true });
551 var nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; });
552 assertEquals(["6","10","30","60","100","300","600","1000"], nonEmptyLabels);
553
554 g.updateOptions({ logscale : false });
555 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
556 }
557
558 /**
559 * Verify that include zero range is properly specified.
560 */
561 AxisLabelsTestCase.prototype.testIncludeZero = function() {
562 var g = new Dygraph("graph", [[0, 500], [1, 1000]], { includeZero : true });
563 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
564
565 g.updateOptions({ includeZero : false });
566 assertEquals(['500','600','700','800','900','1000'], Util.getYLabels());
567 }
568
569 AxisLabelsTestCase.prototype.testAxisLabelFontSize = function() {
570 var graph = document.getElementById("graph");
571 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {});
572
573 // Be sure we're dealing with a 14-point default.
574 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
575
576 var assertFontSize = function(selector, expected) {
577 Util.assertStyleOfChildren(selector, "font-size", expected);
578 }
579
580 assertFontSize($(".dygraph-axis-label-x"), "14px");
581 assertFontSize($(".dygraph-axis-label-y") , "14px");
582
583 g.updateOptions({ axisLabelFontSize : 8});
584 assertFontSize($(".dygraph-axis-label-x"), "8px");
585 assertFontSize($(".dygraph-axis-label-y"), "8px");
586
587 g.updateOptions({
588 axisLabelFontSize : null,
589 axes : {
590 x : { axisLabelFontSize : 5 },
591 }
592 });
593
594 assertFontSize($(".dygraph-axis-label-x"), "5px");
595 assertFontSize($(".dygraph-axis-label-y"), "14px");
596
597 g.updateOptions({
598 axes : {
599 y : { axisLabelFontSize : 20 },
600 }
601 });
602
603 assertFontSize($(".dygraph-axis-label-x"), "5px");
604 assertFontSize($(".dygraph-axis-label-y"), "20px");
605
606 g.updateOptions({
607 series : {
608 Y2 : { axis : "y2" } // copy y2 series to y2 axis.
609 },
610 axes : {
611 y2 : { axisLabelFontSize : 12 },
612 }
613 });
614
615 assertFontSize($(".dygraph-axis-label-x"), "5px");
616 assertFontSize($(".dygraph-axis-label-y1"), "20px");
617 assertFontSize($(".dygraph-axis-label-y2"), "12px");
618 }
619
620 AxisLabelsTestCase.prototype.testAxisLabelFontSizeNull = function() {
621 var graph = document.getElementById("graph");
622 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
623 {
624 axisLabelFontSize: null
625 });
626
627 var assertFontSize = function(selector, expected) {
628 Util.assertStyleOfChildren(selector, "font-size", expected);
629 };
630
631 // Be sure we're dealing with a 14-point default.
632 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
633
634 assertFontSize($(".dygraph-axis-label-x"), "14px");
635 assertFontSize($(".dygraph-axis-label-y"), "14px");
636 }
637
638 AxisLabelsTestCase.prototype.testAxisLabelColor = function() {
639 var graph = document.getElementById("graph");
640 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {});
641
642 // Be sure we're dealing with a black default.
643 assertEquals("black", Dygraph.DEFAULT_ATTRS.axisLabelColor);
644
645 var assertColor = function(selector, expected) {
646 Util.assertStyleOfChildren(selector, "color", expected);
647 }
648
649 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 0)");
650 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
651
652 g.updateOptions({ axisLabelColor : "red"});
653 assertColor($(".dygraph-axis-label-x"), "rgb(255, 0, 0)");
654 assertColor($(".dygraph-axis-label-y"), "rgb(255, 0, 0)");
655
656 g.updateOptions({
657 axisLabelColor : null,
658 axes : {
659 x : { axisLabelColor : "blue" },
660 }
661 });
662
663 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
664 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
665
666 g.updateOptions({
667 axes : {
668 y : { axisLabelColor : "green" },
669 }
670 });
671
672 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
673 assertColor($(".dygraph-axis-label-y"), "rgb(0, 128, 0)");
674
675 g.updateOptions({
676 series : {
677 Y2 : { axis : "y2" } // copy y2 series to y2 axis.
678 },
679 axes : {
680 y2 : { axisLabelColor : "yellow" },
681 }
682 });
683
684 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
685 assertColor($(".dygraph-axis-label-y1"), "rgb(0, 128, 0)");
686 assertColor($(".dygraph-axis-label-y2"), "rgb(255, 255, 0)");
687 }
688
689 AxisLabelsTestCase.prototype.testAxisLabelColorNull = function() {
690 var graph = document.getElementById("graph");
691 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
692 {
693 axisLabelColor: null
694 });
695
696 var assertColor = function(selector, expected) {
697 Util.assertStyleOfChildren(selector, "color", expected);
698 }
699
700 // Be sure we're dealing with a 14-point default.
701 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
702
703 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 0)");
704 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
705 }
706
707 /*
708 * This test shows that the label formatter overrides labelsKMB for all values.
709 */
710 AxisLabelsTestCase.prototype.testLabelFormatterOverridesLabelsKMB = function() {
711 var g = new Dygraph(
712 document.getElementById("graph"),
713 "X,a,b\n" +
714 "1,0,2000\n" +
715 "2,500,1500\n" +
716 "3,1000,1000\n" +
717 "4,2000,0\n", {
718 labelsKMB: true,
719 axisLabelFormatter: function (v) {
720 return v + ":X";
721 }
722 });
723 assertEquals(["0:X","500:X","1000:X","1500:X","2000:X"], Util.getYLabels());
724 assertEquals(["1:X","1.5:X","2:X","2.5:X","3:X","3.5:X"], Util.getXLabels());
725 }
726
727 /*
728 * This test shows that you can override labelsKMB on the axis level.
729 */
730 AxisLabelsTestCase.prototype.testLabelsKMBPerAxis = function() {
731 var g = new Dygraph(
732 document.getElementById("graph"),
733 "x,a,b\n" +
734 "1000,0,2000\n" +
735 "2000,500,1500\n" +
736 "3000,1000,1000\n" +
737 "4000,2000,0\n", {
738 labelsKMB: false,
739 axes: {
740 y2: { labelsKMB: true },
741 x: { labelsKMB: true }
742 },
743 series: {
744 b: { axis: "y2" }
745 }
746 });
747
748 // labelsKMB doesn't apply to the x axis. This value should be different.
749 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
750 assertEquals(["1000", "1500", "2000", "2500", "3000", "3500"], Util.getXLabels());
751 assertEquals( ["0","500","1000","1500","2000"], Util.getYLabels(1));
752 assertEquals(["0","500","1K","1.5K","2K"], Util.getYLabels(2));
753 };
754
755 /*
756 * This test shows that you can override labelsKMG2 on the axis level.
757 */
758 AxisLabelsTestCase.prototype.testLabelsKMBG2IPerAxis = function() {
759 var g = new Dygraph(
760 document.getElementById("graph"),
761 "x,a,b\n" +
762 "1000,0,2000\n" +
763 "2000,500,1500\n" +
764 "3000,1000,1000\n" +
765 "4000,2000,0\n", {
766 labelsKMG2: false,
767 axes: {
768 y2: { labelsKMG2: true },
769 x: { labelsKMG2: true }
770 },
771 series: {
772 b: { axis: "y2" }
773 }
774 });
775
776 // It is weird that labelsKMG2 does something on the x axis but KMB does not.
777 // Plus I can't be sure they're doing the same thing as they're done in different
778 // bits of code.
779 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
780 assertEquals(["1024","1536","2048","2560","3072","3584"], Util.getXLabels());
781 assertEquals( ["0","500","1000","1500","2000"], Util.getYLabels(1));
782 assertEquals(["0","500","1000","1.46k","1.95k"], Util.getYLabels(2));
783 };
784
785 /**
786 * This test shows you can override sigFigs on the axis level.
787 */
788 AxisLabelsTestCase.prototype.testSigFigsPerAxis = function() {
789 var g = new Dygraph(
790 document.getElementById("graph"),
791 "x,a,b\n" +
792 "1000,0,2000\n" +
793 "2000,500,1500\n" +
794 "3000,1000,1000\n" +
795 "4000,2000,0\n", {
796 sigFigs: 2,
797 axes: {
798 y2: { sigFigs: 6 },
799 x: { sigFigs: 8 }
800 },
801 series: {
802 b: { axis: "y2" }
803 }
804
805 });
806 // sigFigs doesn't apply to the x axis. This value should be different.
807 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
808 assertEquals(["1000","1500","2000","2500","3000","3500"], Util.getXLabels());
809 assertEquals(["0.0","5.0e+2","1.0e+3","1.5e+3","2.0e+3"], Util.getYLabels(1));
810 assertEquals(["0.00000","500.000","1000.00","1500.00","2000.00"], Util.getYLabels(2));
811 }
812
813 /**
814 * This test shows you can override digitsAfterDecimal on the axis level.
815 */
816 AxisLabelsTestCase.prototype.testDigitsAfterDecimalPerAxis = function() {
817 var g = new Dygraph(
818 document.getElementById("graph"),
819 "x,a,b\n" +
820 "0.006,0.001,0.008\n" +
821 "0.007,0.002,0.007\n" +
822 "0.008,0.003,0.006\n" +
823 "0.009,0.004,0.005\n", {
824 digitsAfterDecimal: 1,
825 series: {
826 b: { axis: "y2" }
827 }
828
829 });
830
831 g.updateOptions({ axes: { y: { digitsAfterDecimal: 3 }}});
832 assertEquals(["0.001","0.002","0.002","0.003","0.003","0.004","0.004"], Util.getYLabels(1));
833 g.updateOptions({ axes: { y: { digitsAfterDecimal: 4 }}});
834 assertEquals(["0.001","0.0015","0.002","0.0025","0.003","0.0035","0.004"], Util.getYLabels(1));
835 g.updateOptions({ axes: { y: { digitsAfterDecimal: 5 }}});
836 assertEquals(["0.001","0.0015","0.002","0.0025","0.003","0.0035","0.004"], Util.getYLabels(1));
837 g.updateOptions({ axes: { y: { digitsAfterDecimal: null }}});
838 assertEquals(["1e-3","2e-3","2e-3","3e-3","3e-3","4e-3","4e-3"], Util.getYLabels(1));
839
840 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 3 }}});
841 assertEquals(["0.005","0.006","0.006","0.007","0.007","0.008","0.008"], Util.getYLabels(2));
842 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 4 }}});
843 assertEquals(["0.005","0.0055","0.006","0.0065","0.007","0.0075","0.008"], Util.getYLabels(2));
844 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 5 }}});
845 assertEquals(["0.005","0.0055","0.006","0.0065","0.007","0.0075","0.008"], Util.getYLabels(2));
846 g.updateOptions({ axes: { y2: { digitsAfterDecimal: null }}});
847 assertEquals(["5e-3","6e-3","6e-3","7e-3","7e-3","7e-3","8e-3"], Util.getYLabels(2));
848
849
850 // digitsAfterDecimal is ignored for the x-axis.
851 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
852 g.updateOptions({ axes: { x: { digitsAfterDecimal: 3 }}});
853 assertEquals(["0.006","0.006500000000000001","0.007","0.0075","0.008","0.0085"], Util.getXLabels());
854 g.updateOptions({ axes: { x: { digitsAfterDecimal: 4 }}});
855 assertEquals(["0.006","0.006500000000000001","0.007","0.0075","0.008","0.0085"], Util.getXLabels());
856 g.updateOptions({ axes: { x: { digitsAfterDecimal: 5 }}});
857 assertEquals(["0.006","0.006500000000000001","0.007","0.0075","0.008","0.0085"], Util.getXLabels());
858 g.updateOptions({ axes: { x: { digitsAfterDecimal: null }}});
859 assertEquals(["0.006","0.006500000000000001","0.007","0.0075","0.008","0.0085"], Util.getXLabels());
860 }
861
862 /**
863 * This test shows you can override digitsAfterDecimal on the axis level.
864 */
865 AxisLabelsTestCase.prototype.testMaxNumberWidthPerAxis = function() {
866 var g = new Dygraph(
867 document.getElementById("graph"),
868 "x,a,b\n" +
869 "12401,12601,12804\n" +
870 "12402,12602,12803\n" +
871 "12403,12603,12802\n" +
872 "12404,12604,12801\n", {
873 maxNumberWidth: 1,
874 series: {
875 b: { axis: "y2" }
876 }
877 });
878
879 g.updateOptions({ axes: { y: { maxNumberWidth: 4 }}});
880 assertEquals(["1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4"] , Util.getYLabels(1));
881 g.updateOptions({ axes: { y: { maxNumberWidth: 5 }}});
882 assertEquals(["12601","12601.5","12602","12602.5","12603","12603.5","12604"] , Util.getYLabels(1));
883 g.updateOptions({ axes: { y: { maxNumberWidth: null }}});
884 assertEquals(["1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4","1.26e+4"] , Util.getYLabels(1));
885
886 g.updateOptions({ axes: { y2: { maxNumberWidth: 4 }}});
887 assertEquals(["1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4"], Util.getYLabels(2));
888 g.updateOptions({ axes: { y2: { maxNumberWidth: 5 }}});
889 assertEquals(["12801","12801.5","12802","12802.5","12803","12803.5","12804"], Util.getYLabels(2));
890 g.updateOptions({ axes: { y2: { maxNumberWidth: null }}});
891 assertEquals(["1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4","1.28e+4"], Util.getYLabels(2));
892
893 // maxNumberWidth is ignored for the x-axis.
894 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
895 g.updateOptions({ axes: { x: { maxNumberWidth: 4 }}});
896 assertEquals(["12401","12401.5","12402","12402.5","12403","12403.5"], Util.getXLabels());
897 g.updateOptions({ axes: { x: { maxNumberWidth: 5 }}});
898 assertEquals(["12401","12401.5","12402","12402.5","12403","12403.5"], Util.getXLabels());
899 g.updateOptions({ axes: { x: { maxNumberWidth: null }}});
900 assertEquals(["12401","12401.5","12402","12402.5","12403","12403.5"], Util.getXLabels());
901 }
902
903 /*
904 // Regression test for http://code.google.com/p/dygraphs/issues/detail?id=147
905 // Checks that axis labels stay sane across a DST change.
906 AxisLabelsTestCase.prototype.testLabelsCrossDstChange = function() {
907 // (From tests/daylight-savings.html)
908 var g = new Dygraph(
909 document.getElementById("graph"),
910 "Date/Time,Purchases\n" +
911 "2010-11-05 00:00:00,167082\n" +
912 "2010-11-06 00:00:00,168571\n" +
913 "2010-11-07 00:00:00,177796\n" +
914 "2010-11-08 00:00:00,165587\n" +
915 "2010-11-09 00:00:00,164380\n",
916 { width: 1024 }
917 );
918
919 // Dates and "nice" hours: 6AM/PM and noon, not 5AM/11AM/...
920 var okLabels = {
921 '05Nov': true,
922 '06Nov': true,
923 '07Nov': true,
924 '08Nov': true,
925 '09Nov': true,
926 '06:00': true,
927 '12:00': true,
928 '18:00': true
929 };
930
931 var xLabels = Util.getXLabels();
932 for (var i = 0; i < xLabels.length; i++) {
933 assertTrue(okLabels[xLabels[i]]);
934 }
935
936 // This range had issues of its own on tests/daylight-savings.html.
937 g.updateOptions({
938 dateWindow: [1289109997722.8127, 1289261208937.7659]
939 });
940 xLabels = Util.getXLabels();
941 for (var i = 0; i < xLabels.length; i++) {
942 assertTrue(okLabels[xLabels[i]]);
943 }
944 };
945
946
947 // Tests data which crosses a "fall back" at a high enough frequency that you
948 // can see both 1:00 A.M.s.
949 AxisLabelsTestCase.prototype.testLabelsCrossDstChangeHighFreq = function() {
950 // Generate data which crosses the EST/EDT boundary.
951 var dst_data = [];
952 var base_ms = 1383454200000;
953 for (var x = base_ms; x < base_ms + 1000 * 60 * 80; x += 1000) {
954 dst_data.push([new Date(x), x]);
955 }
956
957 var g = new Dygraph(
958 document.getElementById("graph"),
959 dst_data,
960 { width: 1024, labels: ['Date', 'Value'] }
961 );
962
963 assertEquals([
964 '00:50', '00:55',
965 '01:00', '01:05', '01:10', '01:15', '01:20', '01:25',
966 '01:30', '01:35', '01:40', '01:45', '01:50', '01:55',
967 '01:00', '01:05' // 1 AM number two!
968 ], Util.getXLabels());
969
970 // Now zoom past the initial 1 AM. This used to cause trouble.
971 g.updateOptions({
972 dateWindow: [1383454200000 + 15*60*1000, g.xAxisExtremes()[1]]}
973 );
974 assertEquals([
975 '01:05', '01:10', '01:15', '01:20', '01:25',
976 '01:30', '01:35', '01:40', '01:45', '01:50', '01:55',
977 '01:00', '01:05' // 1 AM number two!
978 ], Util.getXLabels());
979 };
980
981
982 // Tests data which crosses a "spring forward" at a low frequency.
983 // Regression test for http://code.google.com/p/dygraphs/issues/detail?id=433
984 AxisLabelsTestCase.prototype.testLabelsCrossSpringForward = function() {
985 var g = new Dygraph(
986 document.getElementById("graph"),
987 "Date/Time,Purchases\n" +
988 "2011-03-11 00:00:00,167082\n" +
989 "2011-03-12 00:00:00,168571\n" +
990 "2011-03-13 00:00:00,177796\n" +
991 "2011-03-14 00:00:00,165587\n" +
992 "2011-03-15 00:00:00,164380\n",
993 {
994 width: 1024,
995 dateWindow: [1299989043119.4365, 1300080693627.4866]
996 });
997
998 var okLabels = {
999 '13Mar': true,
1000 // '02:00': true, // not a real time!
1001 '04:00': true,
1002 '06:00': true,
1003 '08:00': true,
1004 '10:00': true,
1005 '12:00': true,
1006 '14:00': true,
1007 '16:00': true,
1008 '18:00': true,
1009 '20:00': true,
1010 '22:00': true,
1011 '14Mar': true
1012 };
1013
1014 var xLabels = Util.getXLabels();
1015 for (var i = 0; i < xLabels.length; i++) {
1016 assertTrue(okLabels[xLabels[i]]);
1017 }
1018 };
1019
1020 AxisLabelsTestCase.prototype.testLabelsCrossSpringForwardHighFreq = function() {
1021 var base_ms_spring = 1299999000000;
1022 var dst_data_spring = [];
1023 for (var x = base_ms_spring; x < base_ms_spring + 1000 * 60 * 80; x += 1000) {
1024 dst_data_spring.push([new Date(x), x]);
1025 }
1026
1027 var g = new Dygraph(
1028 document.getElementById("graph"),
1029 dst_data_spring,
1030 { width: 1024, labels: ['Date', 'Value'] }
1031 );
1032
1033 assertEquals([
1034 '01:50', '01:55',
1035 '03:00', '03:05', '03:10', '03:15', '03:20', '03:25',
1036 '03:30', '03:35', '03:40', '03:45', '03:50', '03:55',
1037 '04:00', '04:05'
1038 ], Util.getXLabels());
1039 };
1040 */