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