Merge pull request #161 from klausw-g/is-series-locked
authorDan Vanderkam <danvdk@gmail.com>
Thu, 22 Nov 2012 03:07:50 +0000 (19:07 -0800)
committerDan Vanderkam <danvdk@gmail.com>
Thu, 22 Nov 2012 03:07:50 +0000 (19:07 -0800)
Export .isSeriesLocked() API function

1  2 
dygraph.js

diff --combined dygraph.js
@@@ -180,18 -180,6 +180,18 @@@ Dygraph.dateAxisFormatter = function(da
    }
  };
  
 +/**
 + * Standard plotters. These may be used by clients.
 + * Available plotters are:
 + * - Dygraph.Plotters.linePlotter: draws central lines (most common)
 + * - Dygraph.Plotters.errorPlotter: draws error bars
 + * - Dygraph.Plotters.fillPlotter: draws fills under lines (used with fillGraph)
 + *
 + * By default, the plotter is [fillPlotter, errorPlotter, linePlotter].
 + * This causes all the lines to be drawn over all the fills/error bars.
 + */
 +Dygraph.Plotters = DygraphCanvasRenderer._Plotters;
 +
  
  // Default attribute values.
  Dygraph.DEFAULT_ATTRS = {
    rangeSelectorPlotStrokeColor: "#808FAB",
    rangeSelectorPlotFillColor: "#A7B1C4",
  
 +  // The ordering here ensures that central lines always appear above any
 +  // fill bars/error bars.
 +  plotter: [
 +    Dygraph.Plotters.fillPlotter,
 +    Dygraph.Plotters.errorPlotter,
 +    Dygraph.Plotters.linePlotter
 +  ],
 +
    // per-axis options
    axes: {
      x: {
@@@ -408,12 -388,6 +408,12 @@@ Dygraph.prototype.__init__ = function(d
      // TODO(nikhilk): Add any other stackedGraph checks here.
    }
  
 +  // These two options have a bad interaction. See issue 359.
 +  if (attrs.showRangeSelector && attrs.animatedZooms) {
 +    this.warn('You should not set animatedZooms=true when using the range selector.');
 +    attrs.animatedZooms = false;
 +  }
 +
    // Dygraphs has many options, some of which interact with one another.
    // To keep track of everything, we maintain two sets of options:
    //
    // Activate plugins.
    this.plugins_ = [];
    for (var i = 0; i < Dygraph.PLUGINS.length; i++) {
 -    var plugin = Dygraph.PLUGINS[i];
 -    var pluginInstance = new plugin();
 +    var Plugin = Dygraph.PLUGINS[i];
 +    var pluginInstance = new Plugin();
      var pluginDict = {
        plugin: pluginInstance,
        events: {},
   * @private
   */
  Dygraph.prototype.cascadeEvents_ = function(name, extra_props) {
 -  if (!name in this.eventListeners_) return true;
 +  if (!(name in this.eventListeners_)) return true;
  
    // QUESTION: can we use objects & prototypes to speed this up?
    var e = {
   * Axis is an optional parameter. Can be set to 'x' or 'y'.
   *
   * The zoomed status for an axis is set whenever a user zooms using the mouse
 - * or when the dateWindow or valueRange are updated (unless the isZoomedIgnoreProgrammaticZoom
 - * option is also specified).
 + * or when the dateWindow or valueRange are updated (unless the
 + * isZoomedIgnoreProgrammaticZoom option is also specified).
   */
  Dygraph.prototype.isZoomed = function(axis) {
 -  if (axis == null) return this.zoomed_x_ || this.zoomed_y_;
 +  if (axis === null || axis === undefined) {
 +    return this.zoomed_x_ || this.zoomed_y_;
 +  }
    if (axis === 'x') return this.zoomed_x_;
    if (axis === 'y') return this.zoomed_y_;
    throw "axis parameter is [" + axis + "] must be null, 'x' or 'y'.";
@@@ -578,7 -550,7 +578,7 @@@ Dygraph.prototype.attr_ = function(name
        }
        if (seriesName === this.highlightSet_ &&
            this.user_attrs_.hasOwnProperty('highlightSeriesOpts')) {
 -        sources.push(this.user_attrs_['highlightSeriesOpts']);
 +        sources.push(this.user_attrs_.highlightSeriesOpts);
        }
      }
    }
@@@ -1253,10 -1225,6 +1253,10 @@@ Dygraph.prototype.createDragInterface_ 
      boundedDates: null, // [minDate, maxDate]
      boundedValues: null, // [[minValue, maxValue] ...]
  
 +    // We cover iframes during mouse interactions. See comments in
 +    // dygraph-utils.js for more info on why this is a good idea.
 +    tarp: new Dygraph.IFrameTarp(),
 +
      // contextB is the same thing as this context object but renamed.
      initializeMouseDown: function(event, g, contextB) {
        // prevents mouse drags from selecting page text.
        contextB.dragStartX = g.dragGetX_(event, contextB);
        contextB.dragStartY = g.dragGetY_(event, contextB);
        contextB.cancelNextDblclick = false;
 +      contextB.tarp.cover();
      }
    };
  
          delete self.axes_[i].dragValueRange;
        }
      }
 +
 +    context.tarp.uncover();
    };
  
    this.addEvent(document, 'mouseup', this.mouseUpHandler_);
@@@ -1536,9 -1501,7 +1536,9 @@@ Dygraph.prototype.doUnzoom_ = function(
        newValueRanges = [];
        for (i = 0; i < this.axes_.length; i++) {
          var axis = this.axes_[i];
 -        newValueRanges.push(axis.valueRange != null ? axis.valueRange : axis.extremeRange);
 +        newValueRanges.push((axis.valueRange !== null &&
 +                             axis.valueRange !== undefined) ?
 +                            axis.valueRange : axis.extremeRange);
        }
      }
  
@@@ -1670,7 -1633,7 +1670,7 @@@ Dygraph.prototype.findClosestPoint = fu
    var minDist = Infinity;
    var idx = -1;
    var dist, dx, dy, point, closestPoint, closestSeries;
 -  for (var setIdx = 0; setIdx < this.layout_.datasets.length; ++setIdx) {
 +  for ( var setIdx = this.layout_.datasets.length - 1 ; setIdx >= 0 ; --setIdx ) {
      var points = this.layout_.points[setIdx];
      for (var i = 0; i < points.length; ++i) {
        var point = points[i];
@@@ -1740,7 -1703,7 +1740,7 @@@ Dygraph.prototype.findStackedPoint = fu
        }
      }
      // Stop if the point (domX, py) is above this series' upper edge
 -    if (setIdx == 0 || py < domY) {
 +    if (setIdx === 0 || py < domY) {
        closestPoint = p1;
        closestSeries = setIdx;
      }
@@@ -1771,7 -1734,7 +1771,7 @@@ Dygraph.prototype.mouseMove_ = function
  
    var highlightSeriesOpts = this.attr_("highlightSeriesOpts");
    var selectionChanged = false;
-   if (highlightSeriesOpts && !this.lockedSet_) {
+   if (highlightSeriesOpts && !this.isSeriesLocked()) {
      var closest;
      if (this.attr_("stackedGraph")) {
        closest = this.findStackedPoint(canvasx, canvasy);
@@@ -1889,10 -1852,8 +1889,10 @@@ Dygraph.prototype.updateSelection_ = fu
        ctx.fillStyle = 'rgba(255,255,255,' + alpha + ')';
        ctx.fillRect(0, 0, this.width_, this.height_);
      }
 -    var setIdx = this.datasetIndexFromSetName_(this.highlightSet_);
 -    this.plotter_._drawLine(ctx, setIdx);
 +
 +    // Redraw only the highlighted series in the interactive canvas (not the
 +    // static plot canvas, which is where series are usually drawn).
 +    this.plotter_._renderLineChart(this.highlightSet_, ctx);
    } else if (this.previousVerticalX_ >= 0) {
      // Determine the maximum highlight circle size.
      var maxCircleSize = 0;
@@@ -1969,7 -1930,7 +1969,7 @@@ Dygraph.prototype.setSelection = functi
            point = this.layout_.unstackPointAtIndex(setIdx, row);
          }
  
 -        if (!(point.yval === null)) this.selPoints_.push(point);
 +        if (point.yval !== null) this.selPoints_.push(point);
        }
      }
    } else {
@@@ -2064,6 -2025,14 +2064,14 @@@ Dygraph.prototype.getHighlightSeries = 
  };
  
  /**
+  * Returns true if the currently-highlighted series was locked
+  * via setSelection(..., seriesName, true).
+  */
+ Dygraph.prototype.isSeriesLocked = function() {
+   return this.lockedSet_;
+ };
+ /**
   * Fires when there's data available to be graphed.
   * @param {String} data Raw CSV data to be plotted
   * @private
@@@ -2113,7 -2082,7 +2121,7 @@@ Dygraph.prototype.extremeValues_ = func
      // With custom bars, maxY is the max of the high values.
      for (j = 0; j < series.length; j++) {
        y = series[j][1][0];
 -      if (!y) continue;
 +      if (y === null || isNaN(y)) continue;
        var low = y - series[j][1][1];
        var high = y + series[j][1][2];
        if (low > y) low = y;    // this can happen with custom bars,
@@@ -2401,7 -2370,7 +2409,7 @@@ Dygraph.prototype.renderGraph_ = functi
  
    var e = {
      canvas: this.hidden_,
 -    drawingContext: this.hidden_ctx_,
 +    drawingContext: this.hidden_ctx_
    };
    this.cascadeEvents_('willDrawChart', e);
    this.plotter_.render();
@@@ -2937,8 -2906,7 +2945,8 @@@ Dygraph.prototype.parseFloat_ = functio
   */
  Dygraph.prototype.parseCSV_ = function(data) {
    var ret = [];
 -  var lines = data.split("\n");
 +  var line_delimiter = Dygraph.detectLineDelimiter(data);
 +  var lines = data.split(line_delimiter || "\n");
    var vals, j;
  
    // Use the default delimiter or fall back to a tab if that makes sense.
@@@ -3152,7 -3120,7 +3160,7 @@@ Dygraph.prototype.parseDataTable_ = fun
        num = Math.floor((num - 1) / 26);
      }
      return shortText;
 -  }
 +  };
  
    var cols = data.getNumberOfColumns();
    var rows = data.getNumberOfRows();
@@@ -3294,8 -3262,7 +3302,8 @@@ Dygraph.prototype.start_ = function() 
      this.predraw_();
    } else if (typeof data == 'string') {
      // Heuristic: a newline means it's CSV data. Otherwise it's an URL.
 -    if (data.indexOf('\n') >= 0) {
 +    var line_delimiter = Dygraph.detectLineDelimiter(data);
 +    if (line_delimiter) {
        this.loadedEvent_(data);
      } else {
        var req = new XMLHttpRequest();