1c518a8ae334b61b990a97456376471b6afa1ce4
[dygraphs.git] / src / extras / rebase.js
1 /**
2 * @license
3 * Copyright 2015 Petr Shevtsov (petr.shevtsov@gmail.com)
4 * MIT-licensed (http://opensource.org/licenses/MIT)
5 *
6 * Rebase plugin
7 *
8 * On pan/zoom event, each series will rebase to a specified value (e.g. 100) at the
9 * start of the displayed period.
10 *
11 * See http://stats.oecd.org/glossary/detail.asp?ID=2249
12 *
13 * Options:
14 * Value to rebase. Must be either Number or 'percent' or null.
15 *
16 * See tests/straw-broom.html for demo.
17 */
18
19 /*global Dygraph:false */
20
21 (function() {
22 "use strict";
23
24 Dygraph.DataHandlers.RebaseHandler = function(baseOpt) {
25 this.baseOpt = baseOpt;
26 };
27
28 var RebaseHandler = Dygraph.DataHandlers.RebaseHandler;
29 RebaseHandler.prototype = new Dygraph.DataHandlers.DefaultHandler();
30
31 RebaseHandler.rebase = function(value, initial, base) {
32 if (base === "percent") {
33 return (value / initial - 1) * 100;
34 }
35 return value * base / initial;
36 };
37
38 RebaseHandler.prototype.getExtremeYValues = function(series, dateWindow, options) {
39 var minY = null, maxY = null, y;
40 var firstIdx = 0, lastIdx = series.length - 1;
41 var initial = series[firstIdx][1];
42
43 for (var j = firstIdx; j <= lastIdx; j++) {
44 if (j === firstIdx) {
45 y = (this.baseOpt === "percent") ? 0 : this.baseOpt;
46 } else {
47 y = RebaseHandler.rebase(series[j][1], initial, this.baseOpt);
48 }
49 if (y === null || isNaN(y))
50 continue;
51 if (maxY === null || y > maxY) {
52 maxY = y;
53 }
54 if (minY === null || y < minY) {
55 minY = y;
56 }
57 }
58 return [ minY, maxY ];
59 };
60
61 RebaseHandler.prototype.seriesToPoints = function(series, setName, boundaryIdStart){
62 var points = [];
63 var firstIdx = 0;
64 var lastIdx = series.length - 1;
65 var initial = series[firstIdx][1]; // TODO: check for null
66 for (var i = 0; i <= lastIdx; ++i) {
67 var item = series[i];
68 var yraw = item[1];
69 var yval = yraw === null ? null : Dygraph.DataHandler.parseFloat(yraw);
70 if (yval !== null) {
71 if (i === firstIdx) {
72 yval = (this.baseOpt === "percent") ? 0 : this.baseOpt;
73 } else {
74 yval = RebaseHandler.rebase(yval, initial, this.baseOpt);
75 }
76 }
77 var point = {
78 x: NaN,
79 y: NaN,
80 xval: Dygraph.DataHandler.parseFloat(item[0]),
81 yval: yval,
82 name: setName,
83 idx: i + boundaryIdStart
84 };
85 points.push(point);
86 }
87 this.onPointsCreated_(series, points);
88 return points;
89 };
90
91 Dygraph.Plugins.Rebase = (function() {
92 var rebase = function(baseOpt) {
93 var isNum = function(v) {
94 return !isNaN(v) && (typeof v === 'number' || {}.toString.call(v) === '[object Number]');
95 };
96 if (baseOpt === "percent" || isNum(baseOpt)) {
97 this.baseOpt_ = baseOpt;
98 } else {
99 this.baseOpt_ = null;
100 }
101 };
102
103 rebase.prototype.toString = function() {
104 return "Rebase Plugin";
105 };
106
107 rebase.prototype.activate = function(g) {
108 if (this.baseOpt_ === null) {
109 return;
110 }
111 return {
112 predraw: this.predraw
113 };
114 };
115
116 rebase.prototype.predraw = function(e) {
117 var g = e.dygraph;
118
119 if (this.baseOpt_ === "percent") {
120 g.updateOptions({
121 axes: {
122 y: {
123 axisLabelFormatter: function(y) {
124 return y + '%';
125 },
126 valueFormatter: function(y) {
127 return Math.round(y * 100) / 100 + '%';
128 }
129 }
130 }
131 }, true);
132 }
133
134 g.dataHandler_ = new Dygraph.DataHandlers.RebaseHandler(this.baseOpt_);
135 };
136
137 return rebase;
138 })();
139 })();