Merge pull request #557 from danvk/sync-glitch
[dygraphs.git] / dygraph.js
index 2966316..78b45f5 100644 (file)
@@ -190,7 +190,7 @@ Dygraph.numberValueFormatter = function(x, opts) {
  * @private
  */
 Dygraph.numberAxisLabelFormatter = function(x, granularity, opts) {
-  return Dygraph.numberValueFormatter(x, opts);
+  return Dygraph.numberValueFormatter.call(this, x, opts);
 };
 
 /**
@@ -2019,6 +2019,14 @@ Dygraph.prototype.animateSelection_ = function(direction) {
 
   var thisId = ++this.animateId;
   var that = this;
+  var cleanupIfClearing = function() {
+    // if we haven't reached fadeLevel 0 in the max frame time,
+    // ensure that the clear happens and just go to 0
+    if (that.fadeLevel !== 0 && direction < 0) {
+      that.fadeLevel = 0;
+      that.clearSelection();
+    }
+  };
   Dygraph.repeatAndCleanup(
     function(n) {
       // ignore simultaneous animations
@@ -2031,7 +2039,7 @@ Dygraph.prototype.animateSelection_ = function(direction) {
         that.updateSelection_(that.fadeLevel / totalSteps);
       }
     },
-    steps, millis, function() {});
+    steps, millis, cleanupIfClearing);
 };
 
 /**
@@ -2042,6 +2050,7 @@ Dygraph.prototype.animateSelection_ = function(direction) {
 Dygraph.prototype.updateSelection_ = function(opt_animFraction) {
   /*var defaultPrevented = */
   this.cascadeEvents_('select', {
+    selectedRow: this.lastRow_,
     selectedX: this.lastx_,
     selectedPoints: this.selPoints_
   });
@@ -3668,6 +3677,35 @@ Dygraph.prototype.indexFromSetName = function(name) {
 };
 
 /**
+ * Find the row number corresponding to the given x-value.
+ * Returns null if there is no such x-value in the data.
+ * If there are multiple rows with the same x-value, this will return the
+ * first one.
+ * @param {number} xVal The x-value to look for (e.g. millis since epoch).
+ * @return {?number} The row number, which you can pass to getValue(), or null.
+ */
+Dygraph.prototype.getRowForX = function(xVal) {
+  var low = 0,
+      high = this.numRows() - 1;
+
+  while (low <= high) {
+    var idx = (high + low) >> 1;
+    var x = this.getValue(idx, 0);
+    if (x < xVal) {
+      low = idx + 1;
+    } else if (x > xVal) {
+      high = idx - 1;
+    } else if (low != idx) {  // equal, but there may be an earlier match.
+      high = idx;
+    } else {
+      return idx;
+    }
+  }
+
+  return null;
+};
+
+/**
  * Trigger a callback when the dygraph has drawn itself and is ready to be
  * manipulated. This is primarily useful when dygraphs has to do an XHR for the
  * data (i.e. a URL is passed as the data source) and the chart is drawn