pass through (row, col) to valueFormatter
[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.05,0,0.05],
78 Util.makeNumbers(Util.getYLabels()), this.kCloseFloat);
79
80 opts.valueRange = [-0.05, 0.05];
81 g.updateOptions(opts);
82 assertEquals([-0.04,-0.02,0,0.02,0.04],
83 Util.makeNumbers(Util.getYLabels()));
84
85 opts.valueRange = [-0.01, 0.01];
86 g.updateOptions(opts);
87 assertEquals([-0.01,-0.005,0,0.005],
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"], 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","y5","y10","y15"], 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 pixelsPerLabel: 60,
205 axisLabelFormatter : function(x, granularity, opts, dg) {
206 assertTrue(Dygraph.isDateLike(x));
207 assertEquals('number', typeof(granularity));
208 assertEquals('function', typeof(opts));
209 assertEquals('[Dygraph graph]', dg.toString());
210 return 'x' + Util.formatDate(x);
211 }
212 },
213 y : {
214 axisLabelFormatter : function(y, granularity, opts, dg) {
215 assertEquals('number', typeof(y));
216 assertEquals('number', typeof(granularity));
217 assertEquals('function', typeof(opts));
218 assertEquals('[Dygraph graph]', dg.toString());
219 return 'y' + y;
220 }
221 }
222 },
223 labels: ['x', 'y']
224 };
225 var data = [];
226 for (var i = 1; i < 10; i++) {
227 data.push([new Date("2011/01/0" + i), 2 * i]);
228 }
229 var graph = document.getElementById("graph");
230 var g = new Dygraph(graph, data, opts);
231
232 assertEquals(["x2011/01/02","x2011/01/04","x2011/01/06","x2011/01/08"], Util.getXLabels());
233 assertEquals(["y5","y10","y15"], Util.getYLabels());
234
235 g.setSelection(0);
236 assertEquals("2011/01/01: y: 2", Util.getLegend());
237 };
238
239 // This test verifies that when a valueFormatter is set (but not an
240 // axisLabelFormatter), then the valueFormatter is used to format the axis
241 // labels.
242 AxisLabelsTestCase.prototype.testValueFormatter = function () {
243 var opts = {
244 width: 480,
245 height: 320,
246 axes : {
247 x : {
248 valueFormatter: function(x, opts, series_name, dg, row, col) {
249 assertEquals('number', typeof(x));
250 assertEquals('function', typeof(opts));
251 assertEquals('string', typeof(series_name));
252 assertEquals('[Dygraph graph]', dg.toString());
253 assertEquals('number', typeof(row));
254 assertEquals('number', typeof(col));
255 return 'x' + x;
256 }
257 },
258 y : {
259 valueFormatter: function(y, opts, series_name, dg, row, col) {
260 assertEquals('number', typeof(y));
261 assertEquals('function', typeof(opts));
262 assertEquals('string', typeof(series_name));
263 assertEquals('[Dygraph graph]', dg.toString());
264 assertEquals('number', typeof(row));
265 assertEquals('number', typeof(col));
266 return 'y' + y;
267 }
268 }
269 },
270 labels: ['x', 'y']
271 };
272 var data = [];
273 for (var i = 0; i < 10; i++) {
274 data.push([i, 2 * i]);
275 }
276 var graph = document.getElementById("graph");
277 var g = new Dygraph(graph, data, opts);
278
279 // the valueFormatter options do not affect the ticks.
280 assertEquals(['0','2','4','6','8'], Util.getXLabels());
281 assertEquals(["0","5","10","15"],
282 Util.getYLabels());
283
284 // they do affect the legend, however.
285 g.setSelection(2);
286 assertEquals("x2: y: y4", Util.getLegend());
287 };
288
289 AxisLabelsTestCase.prototype.testDateValueFormatter = function () {
290 var opts = {
291 width: 480,
292 height: 320,
293 axes : {
294 x : {
295 pixelsPerLabel: 60,
296 valueFormatter: function(x, opts, series_name, dg, row, col) {
297 assertEquals('number', typeof(x));
298 assertEquals('function', typeof(opts));
299 assertEquals('string', typeof(series_name));
300 assertEquals('[Dygraph graph]', dg.toString());
301 assertEquals('number', typeof(row));
302 assertEquals('number', typeof(col));
303 return 'x' + Util.formatDate(x);
304 }
305 },
306 y : {
307 valueFormatter: function(y, opts, series_name, dg, row, col) {
308 assertEquals('number', typeof(y));
309 assertEquals('function', typeof(opts));
310 assertEquals('string', typeof(series_name));
311 assertEquals('[Dygraph graph]', dg.toString());
312 assertEquals('number', typeof(row));
313 assertEquals('number', typeof(col));
314 return 'y' + y;
315 }
316 }
317 },
318 labels: ['x', 'y']
319 };
320
321 var data = [];
322 for (var i = 1; i < 10; i++) {
323 data.push([new Date("2011/01/0" + i), 2 * i]);
324 }
325 var graph = document.getElementById("graph");
326 var g = new Dygraph(graph, data, opts);
327
328 // valueFormatters do not affect ticks.
329 assertEquals(["02 Jan","04 Jan","06 Jan","08 Jan"], Util.getXLabels());
330 assertEquals(["5","10","15"], Util.getYLabels());
331
332 // the valueFormatter options also affect the legend.
333 g.setSelection(2);
334 assertEquals('x2011/01/03: y: y6', Util.getLegend());
335 };
336
337 // This test verifies that when both a valueFormatter and an axisLabelFormatter
338 // are specified, the axisLabelFormatter takes precedence.
339 AxisLabelsTestCase.prototype.testAxisLabelFormatterPrecedence = function () {
340 var opts = {
341 width: 480,
342 height: 320,
343 axes : {
344 x : {
345 valueFormatter: function(x) {
346 return 'xvf' + x;
347 },
348 axisLabelFormatter: function(x, granularity) {
349 return 'x' + x;
350 }
351 },
352 y : {
353 valueFormatter: function(y) {
354 return 'yvf' + y;
355 },
356 axisLabelFormatter: function(y) {
357 return 'y' + y;
358 }
359 }
360 },
361 labels: ['x', 'y']
362 };
363 var data = [];
364 for (var i = 0; i < 10; i++) {
365 data.push([i, 2 * i]);
366 }
367 var graph = document.getElementById("graph");
368 var g = new Dygraph(graph, data, opts);
369
370 assertEquals(['x0','x2','x4','x6','x8'], Util.getXLabels());
371 assertEquals(["y0","y5","y10","y15"], Util.getYLabels());
372
373 g.setSelection(9);
374 assertEquals("xvf9: y: yvf18", Util.getLegend());
375 };
376
377 // This is the same as the previous test, except that options are added
378 // one-by-one.
379 AxisLabelsTestCase.prototype.testAxisLabelFormatterIncremental = function () {
380 var opts = {
381 width: 480,
382 height: 320,
383 labels: ['x', 'y']
384 };
385 var data = [];
386 for (var i = 0; i < 10; i++) {
387 data.push([i, 2 * i]);
388 }
389 var graph = document.getElementById("graph");
390 var g = new Dygraph(graph, data, opts);
391 g.updateOptions({
392 axes : {
393 x : {
394 valueFormatter: function(x) {
395 return 'xvf' + x;
396 }
397 }
398 }
399 });
400 g.updateOptions({
401 axes : {
402 y : {
403 valueFormatter: function(y) {
404 return 'yvf' + y;
405 }
406 }
407 }
408 });
409 g.updateOptions({
410 axes : {
411 x : {
412 axisLabelFormatter: function(x, granularity) {
413 return 'x' + x;
414 }
415 }
416 }
417 });
418 g.updateOptions({
419 axes : {
420 y : {
421 axisLabelFormatter: function(y) {
422 return 'y' + y;
423 }
424 }
425 }
426 });
427
428 assertEquals(["x0","x2","x4","x6","x8"], Util.getXLabels());
429 assertEquals(["y0","y5","y10","y15"], Util.getYLabels());
430
431 g.setSelection(9);
432 assertEquals("xvf9: y: yvf18", Util.getLegend());
433 };
434
435 AxisLabelsTestCase.prototype.testGlobalFormatters = function() {
436 var opts = {
437 width: 480,
438 height: 320,
439 labels: ['x', 'y'],
440 valueFormatter: function(x) {
441 return 'vf' + x;
442 },
443 axisLabelFormatter: function(x) {
444 return 'alf' + x;
445 }
446 };
447 var data = [];
448 for (var i = 0; i < 10; i++) {
449 data.push([i, 2 * i]);
450 }
451 var graph = document.getElementById("graph");
452 var g = new Dygraph(graph, data, opts);
453
454 assertEquals(['alf0','alf2','alf4','alf6','alf8'], Util.getXLabels());
455 assertEquals(["alf0","alf5","alf10","alf15"], Util.getYLabels());
456
457 g.setSelection(9);
458 assertEquals("vf9: y: vf18", Util.getLegend());
459 };
460
461 AxisLabelsTestCase.prototype.testValueFormatterParameters = function() {
462 var calls = [];
463 // change any functions in list to 'fn' -- functions can't be asserted.
464 var killFunctions = function(list) {
465 var out = [];
466 for (var i = 0; i < list.length; i++) {
467 if (typeof(list[i]) == 'function') {
468 out[i] = 'fn';
469 } else {
470 out[i] = list[i];
471 }
472 }
473 return out;
474 };
475 var taggedRecorder = function(tag) {
476 return function() {
477 calls.push([tag].concat(killFunctions(arguments)));
478 return '';
479 }
480 };
481 var opts = {
482 axes: {
483 x: { valueFormatter: taggedRecorder('x') },
484 y: { valueFormatter: taggedRecorder('y') },
485 y2: { valueFormatter: taggedRecorder('y2') }
486 },
487 series: {
488 'y1': { axis: 'y1'},
489 'y2': { axis: 'y2'}
490 },
491 labels: ['x', 'y1', 'y2']
492 };
493 var data = [
494 [0, 1, 2],
495 [1, 3, 4]
496 ];
497 var graph = document.getElementById('graph');
498 var g = new Dygraph(graph, data, opts);
499
500 assertEquals([], calls);
501 g.setSelection(0);
502 assertEquals([
503 // num or millis, opts, series, dygraph, row, col
504 [ 'x', 0, 'fn', 'x', g, 0, 0],
505 [ 'y', 1, 'fn', 'y1', g, 0, 1],
506 ['y2', 2, 'fn', 'y2', g, 0, 2]
507 ], calls);
508
509 calls = [];
510 g.setSelection(1);
511 assertEquals([
512 [ 'x', 1, 'fn', 'x', g, 1, 0],
513 [ 'y', 3, 'fn', 'y1', g, 1, 1],
514 ['y2', 4, 'fn', 'y2', g, 1, 2]
515 ], calls);
516 };
517
518 AxisLabelsTestCase.prototype.testSeriesOrder = function() {
519 var opts = {
520 width: 480,
521 height: 320
522 };
523 var data = "x,00,01,10,11\n" +
524 "0,101,201,301,401\n" +
525 "1,102,202,302,402\n" +
526 "2,103,203,303,403\n" +
527 "3,104,204,304,404\n"
528 ;
529
530 var graph = document.getElementById("graph");
531 var g = new Dygraph(graph, data, opts);
532
533 g.setSelection(2);
534 assertEquals('2: 00: 103 01: 203 10: 303 11: 403', Util.getLegend());
535
536 // Sanity checks for indexFromSetName
537 assertEquals(0, g.indexFromSetName("x"));
538 assertEquals(1, g.indexFromSetName("00"));
539 assertEquals(null, g.indexFromSetName("abcde"));
540
541 // Verify that we get the label list back in the right order
542 assertEquals(["x", "00", "01", "10", "11"], g.getLabels());
543 };
544
545 AxisLabelsTestCase.prototype.testLabelKMB = function() {
546 var data = [];
547 data.push([0,0]);
548 data.push([1,2000]);
549 data.push([2,1000]);
550
551 var g = new Dygraph(
552 document.getElementById("graph"),
553 data,
554 {
555 labels: [ 'X', 'bar' ],
556 axes : {
557 y: {
558 labelsKMB: true
559 }
560 }
561 }
562 );
563
564 assertEquals(["0", "500", "1K", "1.5K", "2K"], Util.getYLabels());
565 };
566
567 AxisLabelsTestCase.prototype.testLabelKMG2 = function() {
568 var data = [];
569 data.push([0,0]);
570 data.push([1,2000]);
571 data.push([2,1000]);
572
573 var g = new Dygraph(
574 document.getElementById("graph"),
575 data,
576 {
577 labels: [ 'X', 'bar' ],
578 axes : {
579 y: {
580 labelsKMG2: true
581 }
582 }
583 }
584 );
585
586 assertEquals(
587 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
588 Util.getYLabels());
589 };
590
591 // Same as testLabelKMG2 but specifies the option at the
592 // top of the option dictionary.
593 AxisLabelsTestCase.prototype.testLabelKMG2_top = function() {
594 var data = [];
595 data.push([0,0]);
596 data.push([1,2000]);
597 data.push([2,1000]);
598
599 var g = new Dygraph(
600 document.getElementById("graph"),
601 data,
602 {
603 labels: [ 'X', 'bar' ],
604 labelsKMG2: true
605 }
606 );
607
608 assertEquals(
609 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
610 Util.getYLabels());
611 };
612
613 /**
614 * Verify that log scale axis range is properly specified.
615 */
616 AxisLabelsTestCase.prototype.testLogScale = function() {
617 var g = new Dygraph("graph", [[0, 5], [1, 1000]], { logscale : true });
618 var nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; });
619 assertEquals(["5","10","20","50","100","200","500","1000"], nonEmptyLabels);
620
621 g.updateOptions({ logscale : false });
622 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
623 }
624
625 /**
626 * Verify that include zero range is properly specified.
627 */
628 AxisLabelsTestCase.prototype.testIncludeZero = function() {
629 var g = new Dygraph("graph", [[0, 500], [1, 1000]], { includeZero : true });
630 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
631
632 g.updateOptions({ includeZero : false });
633 assertEquals(['500','600','700','800','900','1000'], Util.getYLabels());
634 }
635
636 AxisLabelsTestCase.prototype.testAxisLabelFontSize = function() {
637 var graph = document.getElementById("graph");
638 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {});
639
640 // Be sure we're dealing with a 14-point default.
641 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
642
643 var assertFontSize = function(selector, expected) {
644 Util.assertStyleOfChildren(selector, "font-size", expected);
645 }
646
647 assertFontSize($(".dygraph-axis-label-x"), "14px");
648 assertFontSize($(".dygraph-axis-label-y") , "14px");
649
650 g.updateOptions({ axisLabelFontSize : 8});
651 assertFontSize($(".dygraph-axis-label-x"), "8px");
652 assertFontSize($(".dygraph-axis-label-y"), "8px");
653
654 g.updateOptions({
655 axisLabelFontSize : null,
656 axes : {
657 x : { axisLabelFontSize : 5 },
658 }
659 });
660
661 assertFontSize($(".dygraph-axis-label-x"), "5px");
662 assertFontSize($(".dygraph-axis-label-y"), "14px");
663
664 g.updateOptions({
665 axes : {
666 y : { axisLabelFontSize : 20 },
667 }
668 });
669
670 assertFontSize($(".dygraph-axis-label-x"), "5px");
671 assertFontSize($(".dygraph-axis-label-y"), "20px");
672
673 g.updateOptions({
674 series : {
675 Y2 : { axis : "y2" } // copy y2 series to y2 axis.
676 },
677 axes : {
678 y2 : { axisLabelFontSize : 12 },
679 }
680 });
681
682 assertFontSize($(".dygraph-axis-label-x"), "5px");
683 assertFontSize($(".dygraph-axis-label-y1"), "20px");
684 assertFontSize($(".dygraph-axis-label-y2"), "12px");
685 }
686
687 AxisLabelsTestCase.prototype.testAxisLabelFontSizeNull = function() {
688 var graph = document.getElementById("graph");
689 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
690 {
691 axisLabelFontSize: null
692 });
693
694 var assertFontSize = function(selector, expected) {
695 Util.assertStyleOfChildren(selector, "font-size", expected);
696 };
697
698 // Be sure we're dealing with a 14-point default.
699 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
700
701 assertFontSize($(".dygraph-axis-label-x"), "14px");
702 assertFontSize($(".dygraph-axis-label-y"), "14px");
703 }
704
705 AxisLabelsTestCase.prototype.testAxisLabelColor = function() {
706 var graph = document.getElementById("graph");
707 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData, {});
708
709 // Be sure we're dealing with a black default.
710 assertEquals("black", Dygraph.DEFAULT_ATTRS.axisLabelColor);
711
712 var assertColor = function(selector, expected) {
713 Util.assertStyleOfChildren(selector, "color", expected);
714 }
715
716 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 0)");
717 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
718
719 g.updateOptions({ axisLabelColor : "red"});
720 assertColor($(".dygraph-axis-label-x"), "rgb(255, 0, 0)");
721 assertColor($(".dygraph-axis-label-y"), "rgb(255, 0, 0)");
722
723 g.updateOptions({
724 axisLabelColor : null,
725 axes : {
726 x : { axisLabelColor : "blue" },
727 }
728 });
729
730 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
731 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
732
733 g.updateOptions({
734 axes : {
735 y : { axisLabelColor : "green" },
736 }
737 });
738
739 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
740 assertColor($(".dygraph-axis-label-y"), "rgb(0, 128, 0)");
741
742 g.updateOptions({
743 series : {
744 Y2 : { axis : "y2" } // copy y2 series to y2 axis.
745 },
746 axes : {
747 y2 : { axisLabelColor : "yellow" },
748 }
749 });
750
751 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 255)");
752 assertColor($(".dygraph-axis-label-y1"), "rgb(0, 128, 0)");
753 assertColor($(".dygraph-axis-label-y2"), "rgb(255, 255, 0)");
754 }
755
756 AxisLabelsTestCase.prototype.testAxisLabelColorNull = function() {
757 var graph = document.getElementById("graph");
758 var g = new Dygraph(graph, AxisLabelsTestCase.simpleData,
759 {
760 axisLabelColor: null
761 });
762
763 var assertColor = function(selector, expected) {
764 Util.assertStyleOfChildren(selector, "color", expected);
765 }
766
767 // Be sure we're dealing with a 14-point default.
768 assertEquals(14, Dygraph.DEFAULT_ATTRS.axisLabelFontSize);
769
770 assertColor($(".dygraph-axis-label-x"), "rgb(0, 0, 0)");
771 assertColor($(".dygraph-axis-label-y"), "rgb(0, 0, 0)");
772 }
773
774 /*
775 * This test shows that the label formatter overrides labelsKMB for all values.
776 */
777 AxisLabelsTestCase.prototype.testLabelFormatterOverridesLabelsKMB = function() {
778 var g = new Dygraph(
779 document.getElementById("graph"),
780 "X,a,b\n" +
781 "1,0,2000\n" +
782 "2,500,1500\n" +
783 "3,1000,1000\n" +
784 "4,2000,0\n", {
785 labelsKMB: true,
786 axisLabelFormatter: function (v) {
787 return v + ":X";
788 }
789 });
790 assertEquals(["0:X","500:X","1000:X","1500:X","2000:X"], Util.getYLabels());
791 assertEquals(["1:X","2:X","3:X"], Util.getXLabels());
792 }
793
794 /*
795 * This test shows that you can override labelsKMB on the axis level.
796 */
797 AxisLabelsTestCase.prototype.testLabelsKMBPerAxis = function() {
798 var g = new Dygraph(
799 document.getElementById("graph"),
800 "x,a,b\n" +
801 "1000,0,2000\n" +
802 "2000,500,1500\n" +
803 "3000,1000,1000\n" +
804 "4000,2000,0\n", {
805 labelsKMB: false,
806 axes: {
807 y2: { labelsKMB: true },
808 x: { labelsKMB: true }
809 },
810 series: {
811 b: { axis: "y2" }
812 }
813 });
814
815 // labelsKMB doesn't apply to the x axis. This value should be different.
816 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
817 assertEquals(["1000","2000","3000"], Util.getXLabels());
818 assertEquals( ["0","500","1000","1500","2000"], Util.getYLabels(1));
819 assertEquals(["0","500","1K","1.5K","2K"], Util.getYLabels(2));
820 };
821
822 /*
823 * This test shows that you can override labelsKMG2 on the axis level.
824 */
825 AxisLabelsTestCase.prototype.testLabelsKMBG2IPerAxis = function() {
826 var g = new Dygraph(
827 document.getElementById("graph"),
828 "x,a,b\n" +
829 "1000,0,2000\n" +
830 "2000,500,1500\n" +
831 "3000,1000,1000\n" +
832 "4000,2000,0\n", {
833 labelsKMG2: false,
834 axes: {
835 y2: { labelsKMG2: true },
836 x: { labelsKMG2: true, pixelsPerLabel: 60 }
837 },
838 series: {
839 b: { axis: "y2" }
840 }
841 });
842
843 // It is weird that labelsKMG2 does something on the x axis but KMB does not.
844 // Plus I can't be sure they're doing the same thing as they're done in different
845 // bits of code.
846 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
847 assertEquals(["1024","2048","3072"], Util.getXLabels());
848 assertEquals( ["0","500","1000","1500","2000"], Util.getYLabels(1));
849 assertEquals(["0","500","1000","1.46k","1.95k"], Util.getYLabels(2));
850 };
851
852 /**
853 * This test shows you can override sigFigs on the axis level.
854 */
855 AxisLabelsTestCase.prototype.testSigFigsPerAxis = function() {
856 var g = new Dygraph(
857 document.getElementById("graph"),
858 "x,a,b\n" +
859 "1000,0,2000\n" +
860 "2000,500,1500\n" +
861 "3000,1000,1000\n" +
862 "4000,2000,0\n", {
863 sigFigs: 2,
864 axes: {
865 y2: { sigFigs: 6 },
866 x: { sigFigs: 8 }
867 },
868 series: {
869 b: { axis: "y2" }
870 }
871
872 });
873 // sigFigs doesn't apply to the x axis. This value should be different.
874 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
875 assertEquals(["1000","2000","3000"], Util.getXLabels());
876 assertEquals(["0.0","5.0e+2","1.0e+3","1.5e+3","2.0e+3"], Util.getYLabels(1));
877 assertEquals(["0.00000","500.000","1000.00","1500.00","2000.00"], Util.getYLabels(2));
878 }
879
880 /**
881 * This test shows you can override digitsAfterDecimal on the axis level.
882 */
883 AxisLabelsTestCase.prototype.testDigitsAfterDecimalPerAxis = function() {
884 var g = new Dygraph(
885 document.getElementById("graph"),
886 "x,a,b\n" +
887 "0.006,0.001,0.008\n" +
888 "0.007,0.002,0.007\n" +
889 "0.008,0.003,0.006\n" +
890 "0.009,0.004,0.005\n", {
891 digitsAfterDecimal: 1,
892 series: {
893 b: { axis: "y2" }
894 }
895
896 });
897
898 g.updateOptions({ axes: { y: { digitsAfterDecimal: 3 }}});
899 assertEquals(["0.001","0.002","0.002","0.003","0.003","0.004","0.004"], Util.getYLabels(1));
900 g.updateOptions({ axes: { y: { digitsAfterDecimal: 4 }}});
901 assertEquals(["0.001","0.0015","0.002","0.0025","0.003","0.0035","0.004"], Util.getYLabels(1));
902 g.updateOptions({ axes: { y: { digitsAfterDecimal: 5 }}});
903 assertEquals(["0.001","0.0015","0.002","0.0025","0.003","0.0035","0.004"], Util.getYLabels(1));
904 g.updateOptions({ axes: { y: { digitsAfterDecimal: null }}});
905 assertEquals(["1e-3","2e-3","2e-3","3e-3","3e-3","4e-3","4e-3"], Util.getYLabels(1));
906
907 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 3 }}});
908 assertEquals(["0.005","0.006","0.006","0.007","0.007","0.008","0.008"], Util.getYLabels(2));
909 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 4 }}});
910 assertEquals(["0.005","0.0055","0.006","0.0065","0.007","0.0075","0.008"], Util.getYLabels(2));
911 g.updateOptions({ axes: { y2: { digitsAfterDecimal: 5 }}});
912 assertEquals(["0.005","0.0055","0.006","0.0065","0.007","0.0075","0.008"], Util.getYLabels(2));
913 g.updateOptions({ axes: { y2: { digitsAfterDecimal: null }}});
914 assertEquals(["5e-3","6e-3","6e-3","7e-3","7e-3","7e-3","8e-3"], Util.getYLabels(2));
915
916
917 // digitsAfterDecimal is ignored for the x-axis.
918 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
919 g.updateOptions({ axes: { x: { digitsAfterDecimal: 3 }}});
920 assertEquals(["0.006","0.007","0.008"], Util.getXLabels());
921 g.updateOptions({ axes: { x: { digitsAfterDecimal: 4 }}});
922 assertEquals(["0.006","0.007","0.008"], Util.getXLabels());
923 g.updateOptions({ axes: { x: { digitsAfterDecimal: 5 }}});
924 assertEquals(["0.006","0.007","0.008"], Util.getXLabels());
925 g.updateOptions({ axes: { x: { digitsAfterDecimal: null }}});
926 assertEquals(["0.006","0.007","0.008"], Util.getXLabels());
927 }
928
929 /**
930 * This test shows you can override digitsAfterDecimal on the axis level.
931 */
932 AxisLabelsTestCase.prototype.testMaxNumberWidthPerAxis = function() {
933 var g = new Dygraph(
934 document.getElementById("graph"),
935 "x,a,b\n" +
936 "12401,12601,12804\n" +
937 "12402,12602,12803\n" +
938 "12403,12603,12802\n" +
939 "12404,12604,12801\n", {
940 maxNumberWidth: 1,
941 series: {
942 b: { axis: "y2" }
943 }
944 });
945
946 g.updateOptions({ axes: { y: { maxNumberWidth: 4 }}});
947 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));
948 g.updateOptions({ axes: { y: { maxNumberWidth: 5 }}});
949 assertEquals(["12601","12601.5","12602","12602.5","12603","12603.5","12604"] , Util.getYLabels(1));
950 g.updateOptions({ axes: { y: { maxNumberWidth: null }}});
951 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));
952
953 g.updateOptions({ axes: { y2: { maxNumberWidth: 4 }}});
954 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));
955 g.updateOptions({ axes: { y2: { maxNumberWidth: 5 }}});
956 assertEquals(["12801","12801.5","12802","12802.5","12803","12803.5","12804"], Util.getYLabels(2));
957 g.updateOptions({ axes: { y2: { maxNumberWidth: null }}});
958 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));
959
960 // maxNumberWidth is ignored for the x-axis.
961 // BUG : https://code.google.com/p/dygraphs/issues/detail?id=488
962 g.updateOptions({ axes: { x: { maxNumberWidth: 4 }}});
963 assertEquals(["12401","12402","12403"], Util.getXLabels());
964 g.updateOptions({ axes: { x: { maxNumberWidth: 5 }}});
965 assertEquals(["12401","12402","12403"], Util.getXLabels());
966 g.updateOptions({ axes: { x: { maxNumberWidth: null }}});
967 assertEquals(["12401","12402","12403"], Util.getXLabels());
968 }
969
970 /*
971 // Regression test for http://code.google.com/p/dygraphs/issues/detail?id=147
972 // Checks that axis labels stay sane across a DST change.
973 AxisLabelsTestCase.prototype.testLabelsCrossDstChange = function() {
974 // (From tests/daylight-savings.html)
975 var g = new Dygraph(
976 document.getElementById("graph"),
977 "Date/Time,Purchases\n" +
978 "2010-11-05 00:00:00,167082\n" +
979 "2010-11-06 00:00:00,168571\n" +
980 "2010-11-07 00:00:00,177796\n" +
981 "2010-11-08 00:00:00,165587\n" +
982 "2010-11-09 00:00:00,164380\n",
983 { width: 1024 }
984 );
985
986 // Dates and "nice" hours: 6AM/PM and noon, not 5AM/11AM/...
987 var okLabels = {
988 '05Nov': true,
989 '06Nov': true,
990 '07Nov': true,
991 '08Nov': true,
992 '09Nov': true,
993 '06:00': true,
994 '12:00': true,
995 '18:00': true
996 };
997
998 var xLabels = Util.getXLabels();
999 for (var i = 0; i < xLabels.length; i++) {
1000 assertTrue(okLabels[xLabels[i]]);
1001 }
1002
1003 // This range had issues of its own on tests/daylight-savings.html.
1004 g.updateOptions({
1005 dateWindow: [1289109997722.8127, 1289261208937.7659]
1006 });
1007 xLabels = Util.getXLabels();
1008 for (var i = 0; i < xLabels.length; i++) {
1009 assertTrue(okLabels[xLabels[i]]);
1010 }
1011 };
1012
1013
1014 // Tests data which crosses a "fall back" at a high enough frequency that you
1015 // can see both 1:00 A.M.s.
1016 AxisLabelsTestCase.prototype.testLabelsCrossDstChangeHighFreq = function() {
1017 // Generate data which crosses the EST/EDT boundary.
1018 var dst_data = [];
1019 var base_ms = 1383454200000;
1020 for (var x = base_ms; x < base_ms + 1000 * 60 * 80; x += 1000) {
1021 dst_data.push([new Date(x), x]);
1022 }
1023
1024 var g = new Dygraph(
1025 document.getElementById("graph"),
1026 dst_data,
1027 { width: 1024, labels: ['Date', 'Value'] }
1028 );
1029
1030 assertEquals([
1031 '00:50', '00:55',
1032 '01:00', '01:05', '01:10', '01:15', '01:20', '01:25',
1033 '01:30', '01:35', '01:40', '01:45', '01:50', '01:55',
1034 '01:00', '01:05' // 1 AM number two!
1035 ], Util.getXLabels());
1036
1037 // Now zoom past the initial 1 AM. This used to cause trouble.
1038 g.updateOptions({
1039 dateWindow: [1383454200000 + 15*60*1000, g.xAxisExtremes()[1]]}
1040 );
1041 assertEquals([
1042 '01:05', '01:10', '01:15', '01:20', '01:25',
1043 '01:30', '01:35', '01:40', '01:45', '01:50', '01:55',
1044 '01:00', '01:05' // 1 AM number two!
1045 ], Util.getXLabels());
1046 };
1047
1048
1049 // Tests data which crosses a "spring forward" at a low frequency.
1050 // Regression test for http://code.google.com/p/dygraphs/issues/detail?id=433
1051 AxisLabelsTestCase.prototype.testLabelsCrossSpringForward = function() {
1052 var g = new Dygraph(
1053 document.getElementById("graph"),
1054 "Date/Time,Purchases\n" +
1055 "2011-03-11 00:00:00,167082\n" +
1056 "2011-03-12 00:00:00,168571\n" +
1057 "2011-03-13 00:00:00,177796\n" +
1058 "2011-03-14 00:00:00,165587\n" +
1059 "2011-03-15 00:00:00,164380\n",
1060 {
1061 width: 1024,
1062 dateWindow: [1299989043119.4365, 1300080693627.4866]
1063 });
1064
1065 var okLabels = {
1066 '13Mar': true,
1067 // '02:00': true, // not a real time!
1068 '04:00': true,
1069 '06:00': true,
1070 '08:00': true,
1071 '10:00': true,
1072 '12:00': true,
1073 '14:00': true,
1074 '16:00': true,
1075 '18:00': true,
1076 '20:00': true,
1077 '22:00': true,
1078 '14Mar': true
1079 };
1080
1081 var xLabels = Util.getXLabels();
1082 for (var i = 0; i < xLabels.length; i++) {
1083 assertTrue(okLabels[xLabels[i]]);
1084 }
1085 };
1086
1087 AxisLabelsTestCase.prototype.testLabelsCrossSpringForwardHighFreq = function() {
1088 var base_ms_spring = 1299999000000;
1089 var dst_data_spring = [];
1090 for (var x = base_ms_spring; x < base_ms_spring + 1000 * 60 * 80; x += 1000) {
1091 dst_data_spring.push([new Date(x), x]);
1092 }
1093
1094 var g = new Dygraph(
1095 document.getElementById("graph"),
1096 dst_data_spring,
1097 { width: 1024, labels: ['Date', 'Value'] }
1098 );
1099
1100 assertEquals([
1101 '01:50', '01:55',
1102 '03:00', '03:05', '03:10', '03:15', '03:20', '03:25',
1103 '03:30', '03:35', '03:40', '03:45', '03:50', '03:55',
1104 '04:00', '04:05'
1105 ], Util.getXLabels());
1106 };
1107 */