Add a:visited style to link-interaction (#819)
[dygraphs.git] / tests / interaction.js
CommitLineData
be46943f
RK
1// Code for a variety of interaction models. Used in interaction.html, but split out from
2// that file so they can be tested in isolation.
3//
2c1befcb
RK
4function downV3(event, g, context) {
5 context.initializeMouseDown(event, g, context);
6 if (event.altKey || event.shiftKey) {
7 Dygraph.startZoom(event, g, context);
8 } else {
9 Dygraph.startPan(event, g, context);
10 }
11}
12
13function moveV3(event, g, context) {
14 if (context.isPanning) {
15 Dygraph.movePan(event, g, context);
16 } else if (context.isZooming) {
17 Dygraph.moveZoom(event, g, context);
18 }
19}
20
21function upV3(event, g, context) {
22 if (context.isPanning) {
23 Dygraph.endPan(event, g, context);
24 } else if (context.isZooming) {
25 Dygraph.endZoom(event, g, context);
26 }
27}
28
29// Take the offset of a mouse event on the dygraph canvas and
30// convert it to a pair of percentages from the bottom left.
31// (Not top left, bottom is where the lower value is.)
32function offsetToPercentage(g, offsetX, offsetY) {
33 // This is calculating the pixel offset of the leftmost date.
34 var xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0];
35 var yar0 = g.yAxisRange(0);
36
37 // This is calculating the pixel of the higest value. (Top pixel)
38 var yOffset = g.toDomCoords(null, yar0[1])[1];
39
40 // x y w and h are relative to the corner of the drawing area,
41 // so that the upper corner of the drawing area is (0, 0).
42 var x = offsetX - xOffset;
43 var y = offsetY - yOffset;
44
45 // This is computing the rightmost pixel, effectively defining the
46 // width.
47 var w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset;
48
49 // This is computing the lowest pixel, effectively defining the height.
50 var h = g.toDomCoords(null, yar0[0])[1] - yOffset;
51
52 // Percentage from the left.
53 var xPct = w == 0 ? 0 : (x / w);
54 // Percentage from the top.
55 var yPct = h == 0 ? 0 : (y / h);
56
57 // The (1-) part below changes it from "% distance down from the top"
58 // to "% distance up from the bottom".
59 return [xPct, (1-yPct)];
60}
61
62function dblClickV3(event, g, context) {
63 // Reducing by 20% makes it 80% the original size, which means
64 // to restore to original size it must grow by 25%
417af431
JL
65
66 if (!(event.offsetX && event.offsetY)){
67 event.offsetX = event.layerX - event.target.offsetLeft;
68 event.offsetY = event.layerY - event.target.offsetTop;
69 }
70
2c1befcb
RK
71 var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
72 var xPct = percentages[0];
73 var yPct = percentages[1];
74
75 if (event.ctrlKey) {
76 zoom(g, -.25, xPct, yPct);
77 } else {
78 zoom(g, +.2, xPct, yPct);
79 }
80}
81
9d10bca3 82var lastClickedGraph = null;
fd556f34 83
9d10bca3
RK
84function clickV3(event, g, context) {
85 lastClickedGraph = g;
2b66af4f
DV
86 event.preventDefault();
87 event.stopPropagation();
fd556f34
RK
88}
89
2c1befcb 90function scrollV3(event, g, context) {
9d10bca3 91 if (lastClickedGraph != g) {
fd556f34
RK
92 return;
93 }
2c1befcb
RK
94 var normal = event.detail ? event.detail * -1 : event.wheelDelta / 40;
95 // For me the normalized value shows 0.075 for one click. If I took
96 // that verbatim, it would be a 7.5%.
97 var percentage = normal / 50;
98
417af431
JL
99 if (!(event.offsetX && event.offsetY)){
100 event.offsetX = event.layerX - event.target.offsetLeft;
101 event.offsetY = event.layerY - event.target.offsetTop;
102 }
103
2c1befcb
RK
104 var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
105 var xPct = percentages[0];
106 var yPct = percentages[1];
107
108 zoom(g, percentage, xPct, yPct);
2b66af4f
DV
109 event.preventDefault();
110 event.stopPropagation();
2c1befcb
RK
111}
112
113// Adjusts [x, y] toward each other by zoomInPercentage%
114// Split it so the left/bottom axis gets xBias/yBias of that change and
115// tight/top gets (1-xBias)/(1-yBias) of that change.
116//
117// If a bias is missing it splits it down the middle.
118function zoom(g, zoomInPercentage, xBias, yBias) {
119 xBias = xBias || 0.5;
120 yBias = yBias || 0.5;
121 function adjustAxis(axis, zoomInPercentage, bias) {
122 var delta = axis[1] - axis[0];
123 var increment = delta * zoomInPercentage;
124 var foo = [increment * bias, increment * (1-bias)];
125 return [ axis[0] + foo[0], axis[1] - foo[1] ];
126 }
127 var yAxes = g.yAxisRanges();
128 var newYAxes = [];
129 for (var i = 0; i < yAxes.length; i++) {
130 newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias);
131 }
132
133 g.updateOptions({
134 dateWindow: adjustAxis(g.xAxisRange(), zoomInPercentage, xBias),
135 valueRange: newYAxes[0]
136 });
137}
138
139var v4Active = false;
140var v4Canvas = null;
141
142function downV4(event, g, context) {
143 context.initializeMouseDown(event, g, context);
144 v4Active = true;
145 moveV4(event, g, context); // in case the mouse went down on a data point.
146}
147
148var processed = [];
149
150function moveV4(event, g, context) {
151 var RANGE = 7;
152
153 if (v4Active) {
464b5f50
DV
154 var graphPos = Dygraph.findPos(g.graphDiv);
155 var canvasx = Dygraph.pageX(event) - graphPos.x;
156 var canvasy = Dygraph.pageY(event) - graphPos.y;
2c1befcb
RK
157
158 var rows = g.numRows();
159 // Row layout:
160 // [date, [val1, stdev1], [val2, stdev2]]
161 for (var row = 0; row < rows; row++) {
162 var date = g.getValue(row, 0);
163 var x = g.toDomCoords(date, null)[0];
164 var diff = Math.abs(canvasx - x);
165 if (diff < RANGE) {
166 for (var col = 1; col < 3; col++) {
167 // TODO(konigsberg): these will throw exceptions as data is removed.
168 var vals = g.getValue(row, col);
169 if (vals == null) { continue; }
170 var val = vals[0];
171 var y = g.toDomCoords(null, val)[1];
172 var diff2 = Math.abs(canvasy - y);
173 if (diff2 < RANGE) {
174 var found = false;
175 for (var i in processed) {
176 var stored = processed[i];
177 if(stored[0] == row && stored[1] == col) {
178 found = true;
179 break;
9e9ca2eb 180 }
9e9ca2eb 181 }
2c1befcb
RK
182 if (!found) {
183 processed.push([row, col]);
184 drawV4(x, y);
185 }
186 return;
9e9ca2eb 187 }
9e9ca2eb
RK
188 }
189 }
2c1befcb
RK
190 }
191 }
192}
193
194function upV4(event, g, context) {
195 if (v4Active) {
196 v4Active = false;
197 }
198}
199
200function dblClickV4(event, g, context) {
7d783e00 201 restorePositioning(g);
2c1befcb
RK
202}
203
204function drawV4(x, y) {
205 var ctx = v4Canvas;
206
207 ctx.strokeStyle = "#000000";
208 ctx.fillStyle = "#FFFF00";
209 ctx.beginPath();
210 ctx.arc(x,y,5,0,Math.PI*2,true);
211 ctx.closePath();
212 ctx.stroke();
213 ctx.fill();
214}
215
216function captureCanvas(canvas, area, g) {
217 v4Canvas = canvas;
218}
219
220function restorePositioning(g) {
221 g.updateOptions({
222 dateWindow: null,
223 valueRange: null
224 });
225}