Merge branch 'interactive_on_top' of http://github.com/ecurran/dygraphs
authorDan Vanderkam <danvdk@gmail.com>
Thu, 20 May 2010 21:28:21 +0000 (14:28 -0700)
committerDan Vanderkam <danvdk@gmail.com>
Thu, 20 May 2010 21:28:21 +0000 (14:28 -0700)
1  2 
dygraph.js

diff --combined dygraph.js
@@@ -393,20 -393,24 +393,24 @@@ Dygraph.prototype.createInterface_ = fu
    this.canvas_.height = this.height_;
    this.canvas_.style.width = this.width_ + "px";    // for IE
    this.canvas_.style.height = this.height_ + "px";  // for IE
-   this.graphDiv.appendChild(this.canvas_);
  
    // ... and for static parts of the chart.
    this.hidden_ = this.createPlotKitCanvas_(this.canvas_);
  
+   // The interactive parts of the graph are drawn on top of the chart.
+   this.graphDiv.appendChild(this.hidden_);
+   this.graphDiv.appendChild(this.canvas_);
+   this.mouseEventElement_ = this.canvas_;
    // Make sure we don't overdraw.
    Dygraph.clipCanvas_(this.hidden_, this.clippingArea_);
    Dygraph.clipCanvas_(this.canvas_, this.clippingArea_);
  
    var dygraph = this;
-   Dygraph.addEvent(this.hidden_, 'mousemove', function(e) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mousemove', function(e) {
      dygraph.mouseMove_(e);
    });
-   Dygraph.addEvent(this.hidden_, 'mouseout', function(e) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mouseout', function(e) {
      dygraph.mouseOut_(e);
    });
  
@@@ -482,7 -486,6 +486,6 @@@ Dygraph.prototype.createPlotKitCanvas_ 
    h.height = this.height_;
    h.style.width = this.width_ + "px";    // for IE
    h.style.height = this.height_ + "px";  // for IE
-   this.graphDiv.appendChild(h);
    return h;
  };
  
@@@ -713,7 -716,7 +716,7 @@@ Dygraph.prototype.createDragInterface_ 
    var getY = function(e) { return Dygraph.pageX(e) - py };
  
    // Draw zoom rectangles when the mouse is down and the user moves around
-   Dygraph.addEvent(this.hidden_, 'mousemove', function(event) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mousemove', function(event) {
      if (isZooming) {
        dragEndX = getX(event);
        dragEndY = getY(event);
    });
  
    // Track the beginning of drag events
-   Dygraph.addEvent(this.hidden_, 'mousedown', function(event) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mousedown', function(event) {
      px = Dygraph.findPosX(self.canvas_);
      py = Dygraph.findPosY(self.canvas_);
      dragStartX = getX(event);
    });
  
    // Temporarily cancel the dragging event when the mouse leaves the graph
-   Dygraph.addEvent(this.hidden_, 'mouseout', function(event) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mouseout', function(event) {
      if (isZooming) {
        dragEndX = null;
        dragEndY = null;
  
    // If the mouse is released on the canvas during a drag event, then it's a
    // zoom. Only do the zoom if it's over a large enough area (>= 10 pixels)
-   Dygraph.addEvent(this.hidden_, 'mouseup', function(event) {
+   Dygraph.addEvent(this.mouseEventElement_, 'mouseup', function(event) {
      if (isZooming) {
        isZooming = false;
        dragEndX = getX(event);
    });
  
    // Double-clicking zooms back out
-   Dygraph.addEvent(this.hidden_, 'dblclick', function(event) {
+   Dygraph.addEvent(this.mouseEventElement_, 'dblclick', function(event) {
      if (self.dateWindow_ == null) return;
      self.dateWindow_ = null;
      self.drawGraph_(self.rawData_);
@@@ -885,7 -888,7 +888,7 @@@ Dygraph.prototype.doZoom_ = function(lo
   * @private
   */
  Dygraph.prototype.mouseMove_ = function(event) {
-   var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(this.hidden_);
+   var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(this.mouseEventElement_);
    var points = this.layout_.points;
  
    var lastx = -1;
  
    // Extract the points we've selected
    this.selPoints_ = [];
 -  var cumulative_sum = 0;  // used only if we have a stackedGraph.
    var l = points.length;
 -  var isStacked = this.attr_("stackedGraph");
    if (!this.attr_("stackedGraph")) {
      for (var i = 0; i < l; i++) {
        if (points[i].xval == lastx) {
        }
      }
    } else {
 -    // Stacked points need to be examined in reverse order.
 +    // Need to 'unstack' points starting from the bottom
 +    var cumulative_sum = 0;
      for (var i = l - 1; i >= 0; i--) {
        if (points[i].xval == lastx) {
 -        // Clone the point, since we need to 'unstack' it below.
 -        var p = {};
 +        var p = {};  // Clone the point since we modify it
          for (var k in points[i]) {
            p[k] = points[i][k];
          }
          this.selPoints_.push(p);
        }
      }
 +    this.selPoints_.reverse();
    }
  
    if (this.attr_("highlightCallback")) {
@@@ -1518,14 -1522,12 +1521,14 @@@ Dygraph.prototype.drawGraph_ = function
  
    var connectSeparatedPoints = this.attr_('connectSeparatedPoints');
  
 -  // For stacked series.
 -  var cumulative_y = [];
 -  var stacked_datasets = [];
 +  // Loop over the fields (series).  Go from the last to the first,
 +  // because if they're stacked that's how we accumulate the values.
  
 -  // Loop over all fields in the dataset
 -  for (var i = 1; i < data[0].length; i++) {
 +  var cumulative_y = [];  // For stacked series.
 +  var datasets = [];
 +
 +  // Loop over all fields and create datasets
 +  for (var i = data[0].length - 1; i >= 1; i--) {
      if (!this.visibility()[i - 1]) continue;
  
      var series = [];
      if (maxY === null || thisMaxY > maxY) maxY = thisMaxY;
  
      if (bars) {
 -      var vals = [];
 -      for (var j=0; j<series.length; j++)
 -        vals[j] = [series[j][0],
 -                   series[j][1][0], series[j][1][1], series[j][1][2]];
 -      this.layout_.addDataset(this.attr_("labels")[i], vals);
 +      for (var j=0; j<series.length; j++) {
 +        val = [series[j][0], series[j][1][0], series[j][1][1], series[j][1][2]];
 +        series[j] = val;
 +      }
      } else if (this.attr_("stackedGraph")) {
 -      var vals = [];
        var l = series.length;
        var actual_y;
        for (var j = 0; j < l; j++) {
 -        if (cumulative_y[series[j][0]] === undefined)
 -          cumulative_y[series[j][0]] = 0;
 +        // If one data set has a NaN, let all subsequent stacked
 +        // sets inherit the NaN -- only start at 0 for the first set.
 +        var x = series[j][0];
 +        if (cumulative_y[x] === undefined)
 +          cumulative_y[x] = 0;
  
          actual_y = series[j][1];
 -        cumulative_y[series[j][0]] += actual_y;
 +        cumulative_y[x] += actual_y;
  
 -        vals[j] = [series[j][0], cumulative_y[series[j][0]]]
 +        series[j] = [x, cumulative_y[x]]
  
 -        if (!maxY || cumulative_y[series[j][0]] > maxY)
 -          maxY = cumulative_y[series[j][0]];
 +        if (!maxY || cumulative_y[x] > maxY)
 +          maxY = cumulative_y[x];
        }
 -      stacked_datasets.push([this.attr_("labels")[i], vals]);
 -      //this.layout_.addDataset(this.attr_("labels")[i], vals);
 -    } else {
 -      this.layout_.addDataset(this.attr_("labels")[i], series);
      }
 +
 +    datasets[i] = series;
    }
  
 -  if (stacked_datasets.length > 0) {
 -    for (var i = (stacked_datasets.length - 1); i >= 0; i--) {
 -      this.layout_.addDataset(stacked_datasets[i][0], stacked_datasets[i][1]);
 -    }
 +  for (var i = 1; i < datasets.length; i++) {
 +    this.layout_.addDataset(this.attr_("labels")[i], datasets[i]);
    }
  
    // Use some heuristics to come up with a good maxY value, unless it's been