- return Dygraph.pageY(e) - context.py
-};
-
-// 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;
-}
-
-// Called in response to an interaction model operation that
-// responds to an event that defines zoom boundaries.
-//
-// It's used in the default callback for "mousemove" operations.
-// Custom interaction model builders can use it to provide the default
-// zooming behavior.
-//
-Dygraph.moveZoom = function(event, g, context) {
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
-
- var xDelta = Math.abs(context.dragStartX - context.dragEndX);
- var yDelta = Math.abs(context.dragStartY - context.dragEndY);
-
- // drag direction threshold for y axis is twice as large as x axis
- context.dragDirection = (xDelta < yDelta / 2) ? Dygraph.VERTICAL : Dygraph.HORIZONTAL;
-
- g.drawZoomRect_(
- context.dragDirection,
- context.dragStartX,
- context.dragEndX,
- context.dragStartY,
- context.dragEndY,
- context.prevDragDirection,
- context.prevEndX,
- context.prevEndY);
-
- context.prevEndX = context.dragEndX;
- context.prevEndY = context.dragEndY;
- context.prevDragDirection = context.dragDirection;
-}
-
-// Called in response to an interaction model operation that
-// responds to an event that performs a zoom based on previously defined
-// bounds..
-//
-// It's used in the default callback for "mouseup" operations.
-// Custom interaction model builders can use it to provide the default
-// zooming behavior.
-//
-Dygraph.endZoom = function(event, g, context) {
- context.isZooming = false;
- context.dragEndX = g.dragGetX_(event, context);
- context.dragEndY = g.dragGetY_(event, context);
- var regionWidth = Math.abs(context.dragEndX - context.dragStartX);
- var regionHeight = Math.abs(context.dragEndY - context.dragStartY);
-
- if (regionWidth < 2 && regionHeight < 2 &&
- g.lastx_ != undefined && g.lastx_ != -1) {
- // TODO(danvk): pass along more info about the points, e.g. 'x'
- if (g.attr_('clickCallback') != null) {
- g.attr_('clickCallback')(event, g.lastx_, g.selPoints_);
- }
- if (g.attr_('pointClickCallback')) {
- // check if the click was on a particular point.
- var closestIdx = -1;
- var closestDistance = 0;
- for (var i = 0; i < g.selPoints_.length; i++) {
- var p = g.selPoints_[i];
- var distance = Math.pow(p.canvasx - context.dragEndX, 2) +
- Math.pow(p.canvasy - context.dragEndY, 2);
- if (closestIdx == -1 || distance < closestDistance) {
- closestDistance = distance;
- closestIdx = i;
- }
- }
-
- // Allow any click within two pixels of the dot.
- var radius = g.attr_('highlightCircleSize') + 2;
- if (closestDistance <= 5 * 5) {
- g.attr_('pointClickCallback')(event, g.selPoints_[closestIdx]);
- }
- }
- }
-
- if (regionWidth >= 10 && context.dragDirection == Dygraph.HORIZONTAL) {
- g.doZoomX_(Math.min(context.dragStartX, context.dragEndX),
- Math.max(context.dragStartX, context.dragEndX));
- } else if (regionHeight >= 10 && context.dragDirection == Dygraph.VERTICAL) {
- g.doZoomY_(Math.min(context.dragStartY, context.dragEndY),
- Math.max(context.dragStartY, context.dragEndY));
- } else {
- g.canvas_.getContext("2d").clearRect(0, 0,
- g.canvas_.width,
- g.canvas_.height);
- }
- context.dragStartX = null;
- context.dragStartY = null;
-}
-
-Dygraph.defaultInteractionModel = {
- // Track the beginning of drag events
- mousedown: function(event, g, context) {
- context.initializeMouseDown(event, g, context);
-
- if (event.altKey || event.shiftKey) {
- Dygraph.startPan(event, g, context);
- } else {
- Dygraph.startZoom(event, g, context);
- }
- },
-
- // Draw zoom rectangles when the mouse is down and the user moves around
- mousemove: function(event, g, context) {
- if (context.isZooming) {
- Dygraph.moveZoom(event, g, context);
- } else if (context.isPanning) {
- Dygraph.movePan(event, g, context);
- }
- },
-
- mouseup: function(event, g, context) {
- if (context.isZooming) {
- Dygraph.endZoom(event, g, context);
- } else if (context.isPanning) {
- Dygraph.endPan(event, g, context);
- }
- },
-
- // Temporarily cancel the dragging event when the mouse leaves the graph
- mouseout: function(event, g, context) {
- if (context.isZooming) {
- context.dragEndX = null;
- context.dragEndY = null;
- }
- },
-
- // Disable zooming out if panning.
- dblclick: function(event, g, context) {
- if (event.altKey || event.shiftKey) {
- return;
- }
- // TODO(konigsberg): replace g.doUnzoom()_ with something that is
- // friendlier to public use.
- g.doUnzoom_();
- }