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