--- /dev/null
+// Code for a variety of interaction models. Used in interaction.html, but split out from
+// that file so they can be tested in isolation.
+//
+function downV3(event, g, context) {
+ context.initializeMouseDown(event, g, context);
+ if (event.altKey || event.shiftKey) {
+ Dygraph.startZoom(event, g, context);
+ } else {
+ Dygraph.startPan(event, g, context);
+ }
+}
+
+function moveV3(event, g, context) {
+ if (context.isPanning) {
+ Dygraph.movePan(event, g, context);
+ } else if (context.isZooming) {
+ Dygraph.moveZoom(event, g, context);
+ }
+}
+
+function upV3(event, g, context) {
+ if (context.isPanning) {
+ Dygraph.endPan(event, g, context);
+ } else if (context.isZooming) {
+ Dygraph.endZoom(event, g, context);
+ }
+}
+
+// Take the offset of a mouse event on the dygraph canvas and
+// convert it to a pair of percentages from the bottom left.
+// (Not top left, bottom is where the lower value is.)
+function offsetToPercentage(g, offsetX, offsetY) {
+ // This is calculating the pixel offset of the leftmost date.
+ var xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0];
+ var yar0 = g.yAxisRange(0);
+
+ // This is calculating the pixel of the higest value. (Top pixel)
+ var yOffset = g.toDomCoords(null, yar0[1])[1];
+
+ // x y w and h are relative to the corner of the drawing area,
+ // so that the upper corner of the drawing area is (0, 0).
+ var x = offsetX - xOffset;
+ var y = offsetY - yOffset;
+
+ // This is computing the rightmost pixel, effectively defining the
+ // width.
+ var w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset;
+
+ // This is computing the lowest pixel, effectively defining the height.
+ var h = g.toDomCoords(null, yar0[0])[1] - yOffset;
+
+ // Percentage from the left.
+ var xPct = w == 0 ? 0 : (x / w);
+ // Percentage from the top.
+ var yPct = h == 0 ? 0 : (y / h);
+
+ // The (1-) part below changes it from "% distance down from the top"
+ // to "% distance up from the bottom".
+ return [xPct, (1-yPct)];
+}
+
+function dblClickV3(event, g, context) {
+ // Reducing by 20% makes it 80% the original size, which means
+ // to restore to original size it must grow by 25%
+ var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
+ var xPct = percentages[0];
+ var yPct = percentages[1];
+
+ if (event.ctrlKey) {
+ zoom(g, -.25, xPct, yPct);
+ } else {
+ zoom(g, +.2, xPct, yPct);
+ }
+}
+
+var lastClickedGraph = null;
+
+function clickV3(event, g, context) {
+ lastClickedGraph = g;
+ Dygraph.cancelEvent(event);
+}
+
+function scrollV3(event, g, context) {
+ if (lastClickedGraph != g) {
+ return;
+ }
+ var normal = event.detail ? event.detail * -1 : event.wheelDelta / 40;
+ // For me the normalized value shows 0.075 for one click. If I took
+ // that verbatim, it would be a 7.5%.
+ var percentage = normal / 50;
+
+ var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
+ var xPct = percentages[0];
+ var yPct = percentages[1];
+
+ zoom(g, percentage, xPct, yPct);
+ Dygraph.cancelEvent(event);
+}
+
+// Adjusts [x, y] toward each other by zoomInPercentage%
+// Split it so the left/bottom axis gets xBias/yBias of that change and
+// tight/top gets (1-xBias)/(1-yBias) of that change.
+//
+// If a bias is missing it splits it down the middle.
+function zoom(g, zoomInPercentage, xBias, yBias) {
+ xBias = xBias || 0.5;
+ yBias = yBias || 0.5;
+ function adjustAxis(axis, zoomInPercentage, bias) {
+ var delta = axis[1] - axis[0];
+ var increment = delta * zoomInPercentage;
+ var foo = [increment * bias, increment * (1-bias)];
+ return [ axis[0] + foo[0], axis[1] - foo[1] ];
+ }
+ var yAxes = g.yAxisRanges();
+ var newYAxes = [];
+ for (var i = 0; i < yAxes.length; i++) {
+ newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias);
+ }
+
+ g.updateOptions({
+ dateWindow: adjustAxis(g.xAxisRange(), zoomInPercentage, xBias),
+ valueRange: newYAxes[0]
+ });
+}
+
+var v4Active = false;
+var v4Canvas = null;
+
+function downV4(event, g, context) {
+ context.initializeMouseDown(event, g, context);
+ v4Active = true;
+ moveV4(event, g, context); // in case the mouse went down on a data point.
+}
+
+var processed = [];
+
+function moveV4(event, g, context) {
+ var RANGE = 7;
+
+ if (v4Active) {
+ var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(g.graphDiv);
+ var canvasy = Dygraph.pageY(event) - Dygraph.findPosY(g.graphDiv);
+
+ var rows = g.numRows();
+ // Row layout:
+ // [date, [val1, stdev1], [val2, stdev2]]
+ for (var row = 0; row < rows; row++) {
+ var date = g.getValue(row, 0);
+ var x = g.toDomCoords(date, null)[0];
+ var diff = Math.abs(canvasx - x);
+ if (diff < RANGE) {
+ for (var col = 1; col < 3; col++) {
+ // TODO(konigsberg): these will throw exceptions as data is removed.
+ var vals = g.getValue(row, col);
+ if (vals == null) { continue; }
+ var val = vals[0];
+ var y = g.toDomCoords(null, val)[1];
+ var diff2 = Math.abs(canvasy - y);
+ if (diff2 < RANGE) {
+ var found = false;
+ for (var i in processed) {
+ var stored = processed[i];
+ if(stored[0] == row && stored[1] == col) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ processed.push([row, col]);
+ drawV4(x, y);
+ }
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+function upV4(event, g, context) {
+ if (v4Active) {
+ v4Active = false;
+ }
+}
+
+function dblClickV4(event, g, context) {
+ restorePositioning(g);
+}
+
+function drawV4(x, y) {
+ var ctx = v4Canvas;
+
+ ctx.strokeStyle = "#000000";
+ ctx.fillStyle = "#FFFF00";
+ ctx.beginPath();
+ ctx.arc(x,y,5,0,Math.PI*2,true);
+ ctx.closePath();
+ ctx.stroke();
+ ctx.fill();
+}
+
+function captureCanvas(canvas, area, g) {
+ v4Canvas = canvas;
+}
+
+function restorePositioning(g) {
+ g.updateOptions({
+ dateWindow: null,
+ valueRange: null
+ });
+}
-// Code for a variety of interaction models. Used in interaction.html, but split out from
-// that file so they can be tested in isolation.
-//
-function downV3(event, g, context) {
- context.initializeMouseDown(event, g, context);
- if (event.altKey || event.shiftKey) {
- Dygraph.startZoom(event, g, context);
- } else {
- Dygraph.startPan(event, g, context);
- }
-}
-
-function moveV3(event, g, context) {
- if (context.isPanning) {
- Dygraph.movePan(event, g, context);
- } else if (context.isZooming) {
- Dygraph.moveZoom(event, g, context);
- }
-}
-
-function upV3(event, g, context) {
- if (context.isPanning) {
- Dygraph.endPan(event, g, context);
- } else if (context.isZooming) {
- Dygraph.endZoom(event, g, context);
- }
-}
-
-// Take the offset of a mouse event on the dygraph canvas and
-// convert it to a pair of percentages from the bottom left.
-// (Not top left, bottom is where the lower value is.)
-function offsetToPercentage(g, offsetX, offsetY) {
- // This is calculating the pixel offset of the leftmost date.
- var xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0];
- var yar0 = g.yAxisRange(0);
-
- // This is calculating the pixel of the higest value. (Top pixel)
- var yOffset = g.toDomCoords(null, yar0[1])[1];
-
- // x y w and h are relative to the corner of the drawing area,
- // so that the upper corner of the drawing area is (0, 0).
- var x = offsetX - xOffset;
- var y = offsetY - yOffset;
-
- // This is computing the rightmost pixel, effectively defining the
- // width.
- var w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset;
-
- // This is computing the lowest pixel, effectively defining the height.
- var h = g.toDomCoords(null, yar0[0])[1] - yOffset;
-
- // Percentage from the left.
- var xPct = w == 0 ? 0 : (x / w);
- // Percentage from the top.
- var yPct = h == 0 ? 0 : (y / h);
-
- // The (1-) part below changes it from "% distance down from the top"
- // to "% distance up from the bottom".
- return [xPct, (1-yPct)];
-}
-
-function dblClickV3(event, g, context) {
- // Reducing by 20% makes it 80% the original size, which means
- // to restore to original size it must grow by 25%
- var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
- var xPct = percentages[0];
- var yPct = percentages[1];
-
- if (event.ctrlKey) {
- zoom(g, -.25, xPct, yPct);
- } else {
- zoom(g, +.2, xPct, yPct);
- }
-}
-
-var lastClickedGraph = null;
-
-function clickV3(event, g, context) {
- lastClickedGraph = g;
- Dygraph.cancelEvent(event);
-}
-
-function scrollV3(event, g, context) {
- if (lastClickedGraph != g) {
- return;
- }
- var normal = event.detail ? event.detail * -1 : event.wheelDelta / 40;
- // For me the normalized value shows 0.075 for one click. If I took
- // that verbatim, it would be a 7.5%.
- var percentage = normal / 50;
-
- var percentages = offsetToPercentage(g, event.offsetX, event.offsetY);
- var xPct = percentages[0];
- var yPct = percentages[1];
-
- zoom(g, percentage, xPct, yPct);
- Dygraph.cancelEvent(event);
-}
-
-// Adjusts [x, y] toward each other by zoomInPercentage%
-// Split it so the left/bottom axis gets xBias/yBias of that change and
-// tight/top gets (1-xBias)/(1-yBias) of that change.
-//
-// If a bias is missing it splits it down the middle.
-function zoom(g, zoomInPercentage, xBias, yBias) {
- xBias = xBias || 0.5;
- yBias = yBias || 0.5;
- function adjustAxis(axis, zoomInPercentage, bias) {
- var delta = axis[1] - axis[0];
- var increment = delta * zoomInPercentage;
- var foo = [increment * bias, increment * (1-bias)];
- return [ axis[0] + foo[0], axis[1] - foo[1] ];
- }
- var yAxes = g.yAxisRanges();
- var newYAxes = [];
- for (var i = 0; i < yAxes.length; i++) {
- newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias);
- }
-
- g.updateOptions({
- dateWindow: adjustAxis(g.xAxisRange(), zoomInPercentage, xBias),
- valueRange: newYAxes[0]
- });
-}
-
-var v4Active = false;
-var v4Canvas = null;
-
-function downV4(event, g, context) {
- context.initializeMouseDown(event, g, context);
- v4Active = true;
- moveV4(event, g, context); // in case the mouse went down on a data point.
-}
-
-var processed = [];
-
-function moveV4(event, g, context) {
- var RANGE = 7;
-
- if (v4Active) {
- var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(g.graphDiv);
- var canvasy = Dygraph.pageY(event) - Dygraph.findPosY(g.graphDiv);
-
- var rows = g.numRows();
- // Row layout:
- // [date, [val1, stdev1], [val2, stdev2]]
- for (var row = 0; row < rows; row++) {
- var date = g.getValue(row, 0);
- var x = g.toDomCoords(date, null)[0];
- var diff = Math.abs(canvasx - x);
- if (diff < RANGE) {
- for (var col = 1; col < 3; col++) {
- // TODO(konigsberg): these will throw exceptions as data is removed.
- var vals = g.getValue(row, col);
- if (vals == null) { continue; }
- var val = vals[0];
- var y = g.toDomCoords(null, val)[1];
- var diff2 = Math.abs(canvasy - y);
- if (diff2 < RANGE) {
- var found = false;
- for (var i in processed) {
- var stored = processed[i];
- if(stored[0] == row && stored[1] == col) {
- found = true;
- break;
- }
- }
- if (!found) {
- processed.push([row, col]);
- drawV4(x, y);
- }
- return;
- }
- }
+Gallery.register(
+ 'interaction',
+ {
+ name: 'Custom interaction models',
+ title: 'title',
+ setup: function(parent) {
+ parent.innerHTML =
+ "<table border='1'>" +
+ "<tr><td>" +
+ "<b>Default interaction model</b>" +
+ "<div id='div_g' style='width:600px; height:300px;'></div>" +
+ "</td><td>Zoom: click-drag<br/>Pan: shift-click-drag<br/>Restore zoom level: double-click<br/>" +
+ "</td></tr>" +
+ "<tr><td>" +
+ "<b>No interaction model</b>" +
+ "<div id='div_g2' style='width:600px; height:300px;'></div>" +
+ "</td><td>Click and drag all you like, it won't do anything!" +
+ "<div id='g2_console'></div>" +
+ "</td></tr>" +
+ "<tr><td>" +
+ "<b>Custom interaction model</b>" +
+ "<button id='restore3'>Restore Position</button>" +
+ "<div id='div_g3' style='width:600px; height:300px;'></div>" +
+ "</td><td>" +
+ "Zoom in: double-click, scroll wheel<br/>" +
+ "Zoom out: ctrl-double-click, scroll wheel<br/>" +
+ "Standard Zoom: shift-click-drag" +
+ "Standard Pan: click-drag<br/>" +
+ "Restore zoom level: press button<br/>" +
+ "</td></tr>" +
+ "<tr><td>" +
+ "<b>Fun model!</b>" +
+ "<div id='div_g4' style='width:600px; height:300px;'></div>" +
+ "</td><td>" +
+ "Keep the mouse button pressed, and hover over all points" +
+ "to mark them." +
+ "</td></tr>" +
+ "</table>";
+
+ },
+ run: function() {
+ // TODO(konigsberg): Add cleanup to remove callbacks.
+ Dygraph.addEvent(document, "mousewheel", function() { lastClickedGraph = null; });
+ Dygraph.addEvent(document, "click", function() { lastClickedGraph = null; });
+ var g = new Dygraph(document.getElementById("div_g"),
+ NoisyData, { errorBars : true });
+ var s = document.getElementById("g2_console");
+ var g2 = new Dygraph(document.getElementById("div_g2"),
+ NoisyData,
+ {
+ errorBars : true,
+ interactionModel: {}
+ });
+ var g3 = new Dygraph(document.getElementById("div_g3"),
+ NoisyData, { errorBars : true, interactionModel : {
+ 'mousedown' : downV3,
+ 'mousemove' : moveV3,
+ 'mouseup' : upV3,
+ 'click' : clickV3,
+ 'dblclick' : dblClickV3,
+ 'mousewheel' : scrollV3
+ }});
+ document.getElementById("restore3").onclick = function() {
+ restorePositioning(g3);
}
+ var g4 = new Dygraph(document.getElementById("div_g4"),
+ NoisyData, { errorBars : true, drawPoints : true, interactionModel : {
+ 'mousedown' : downV4,
+ 'mousemove' : moveV4,
+ 'mouseup' : upV4,
+ 'dblclick' : dblClickV4,
+ },
+ underlayCallback : captureCanvas
+ });
}
- }
-}
-
-function upV4(event, g, context) {
- if (v4Active) {
- v4Active = false;
- }
-}
-
-function dblClickV4(event, g, context) {
- restorePositioning(g4);
-}
-
-function drawV4(x, y) {
- var ctx = v4Canvas;
-
- ctx.strokeStyle = "#000000";
- ctx.fillStyle = "#FFFF00";
- ctx.beginPath();
- ctx.arc(x,y,5,0,Math.PI*2,true);
- ctx.closePath();
- ctx.stroke();
- ctx.fill();
-}
-
-function captureCanvas(canvas, area, g) {
- v4Canvas = canvas;
-}
-
-function restorePositioning(g) {
- g.updateOptions({
- dateWindow: null,
- valueRange: null
});
-}