+// Called in response to an interaction model operation that
+// should start the default panning behavior.
+//
+// It's used in the default callback for "mousedown" operations.
+// Custom interaction model builders can use it to provide the default
+// panning behavior.
+//
+Dygraph.startPan = function(event, g, context) {
+ context.isPanning = true;
+ var xRange = g.xAxisRange();
+ context.dateRange = xRange[1] - xRange[0];
+ context.initialLeftmostDate = xRange[0];
+ context.xUnitsPerPixel = context.dateRange / (g.plotter_.area.w - 1);
+
+ // Record the range of each y-axis at the start of the drag.
+ // If any axis has a valueRange or valueWindow, then we want a 2D pan.
+ context.is2DPan = false;
+ for (var i = 0; i < g.axes_.length; i++) {
+ var axis = g.axes_[i];
+ var yRange = g.yAxisRange(i);
+ // TODO(konigsberg): These values should be in |context|.
+ // In log scale, initialTopValue, dragValueRange and unitsPerPixel are log scale.
+ if (axis.logscale) {
+ axis.initialTopValue = Dygraph.log10(yRange[1]);
+ axis.dragValueRange = Dygraph.log10(yRange[1]) - Dygraph.log10(yRange[0]);
+ } else {
+ axis.initialTopValue = yRange[1];
+ axis.dragValueRange = yRange[1] - yRange[0];
+ }
+ axis.unitsPerPixel = axis.dragValueRange / (g.plotter_.area.h - 1);
+
+ // While calculating axes, set 2dpan.
+ if (axis.valueWindow || axis.valueRange) context.is2DPan = true;
+ }
+};
+
+// Called in response to an interaction model operation that
+// responds to an event that pans the view.
+//
+// It's used in the default callback for "mousemove" operations.
+// Custom interaction model builders can use it to provide the default
+// panning behavior.
+//
+Dygraph.movePan = function(event, g, context) {
+ context.dragEndX = g.dragGetX_(event, context);
+ context.dragEndY = g.dragGetY_(event, context);
+
+ var minDate = context.initialLeftmostDate -
+ (context.dragEndX - context.dragStartX) * context.xUnitsPerPixel;
+ var maxDate = minDate + context.dateRange;
+ g.dateWindow_ = [minDate, maxDate];
+
+ // y-axis scaling is automatic unless this is a full 2D pan.
+ if (context.is2DPan) {
+ // Adjust each axis appropriately.
+ for (var i = 0; i < g.axes_.length; i++) {
+ var axis = g.axes_[i];
+
+ var pixelsDragged = context.dragEndY - context.dragStartY;
+ var unitsDragged = pixelsDragged * axis.unitsPerPixel;
+
+ // In log scale, maxValue and minValue are the logs of those values.
+ var maxValue = axis.initialTopValue + unitsDragged;
+ var minValue = maxValue - axis.dragValueRange;
+ if (axis.logscale) {
+ axis.valueWindow = [ Math.pow(Dygraph.LOG_SCALE, minValue),
+ Math.pow(Dygraph.LOG_SCALE, maxValue) ];
+ } else {
+ axis.valueWindow = [ minValue, maxValue ];
+ }
+ }
+ }
+
+ g.drawGraph_();
+}
+
+// Called in response to an interaction model operation that
+// responds to an event that ends panning.
+//
+// It's used in the default callback for "mouseup" operations.
+// Custom interaction model builders can use it to provide the default
+// panning behavior.
+//
+Dygraph.endPan = function(event, g, context) {
+ // TODO(konigsberg): Clear the context data from the axis.
+ // TODO(konigsberg): mouseup should just delete the
+ // context object, and mousedown should create a new one.
+ context.isPanning = false;
+ context.is2DPan = false;
+ context.initialLeftmostDate = null;
+ context.dateRange = null;
+ context.valueRange = null;
+}
+
+// Called in response to an interaction model operation that
+// responds to an event that starts zooming.
+//
+// It's used in the default callback for "mousedown" operations.
+// Custom interaction model builders can use it to provide the default
+// zooming behavior.
+//
+Dygraph.startZoom = function(event, g, context) {
+ context.isZooming = true;
+}