fix bug in tests/resize.html
[dygraphs.git] / dygraph.js
index 0f297fe..b5afc7c 100644 (file)
@@ -85,7 +85,6 @@ Dygraph.toString = function() {
 Dygraph.DEFAULT_ROLL_PERIOD = 1;
 Dygraph.DEFAULT_WIDTH = 480;
 Dygraph.DEFAULT_HEIGHT = 320;
-Dygraph.AXIS_LINE_WIDTH = 0.3;
 
 Dygraph.LOG_SCALE = 10;
 Dygraph.LN_TEN = Math.log(Dygraph.LOG_SCALE);
@@ -154,6 +153,18 @@ Dygraph.DEFAULT_ATTRS = {
   xLabelHeight: 18,
   yLabelWidth: 18,
 
+  drawXAxis: true,
+  drawYAxis: true,
+  axisLineColor: "black",
+  axisLineWidth: 0.3,
+  gridLineWidth: 0.3,
+  axisLabelColor: "black",
+  axisLabelFont: "Arial",  // TODO(danvk): is this implemented?
+  axisLabelWidth: 50,
+  drawYGrid: true,
+  drawXGrid: true,
+  gridLineColor: "rgb(128,128,128)",
+
   interactionModel: null  // will be set to Dygraph.defaultInteractionModel.
 };
 
@@ -293,9 +304,6 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
 
   this.boundaryIds_ = [];
 
-  // Make a note of whether labels will be pulled from the CSV file.
-  this.labelsFromCSV_ = (this.attr_("labels") == null);
-
   // Create the containing DIV and other interactive elements
   this.createInterface_();
 
@@ -548,7 +556,7 @@ Dygraph.prototype.toDataYCoord = function(y, axis) {
 
   if (typeof(axis) == "undefined") axis = 0;
   if (!this.axes_[axis].logscale) {
-    return yRange[0] + (area.h - y) / area.h * (yRange[1] - yRange[0]);
+    return yRange[0] + (area.y + area.h - y) / area.h * (yRange[1] - yRange[0]);
   } else {
     // Computing the inverse of toDomCoord.
     var pct = (y - area.y) / area.h
@@ -760,13 +768,6 @@ Dygraph.prototype.createInterface_ = function() {
   // Create the grapher
   this.layout_ = new DygraphLayout(this);
 
-  // TODO(danvk): why does the Renderer need its own set of options?
-  this.renderOptions_ = { colorScheme: this.colors_,
-                          strokeColor: null,
-                          axisLineWidth: Dygraph.AXIS_LINE_WIDTH };
-  Dygraph.update(this.renderOptions_, this.attrs_);
-  Dygraph.update(this.renderOptions_, this.user_attrs_);
-
   this.createStatusMessage_();
   this.createDragInterface_();
 };
@@ -871,8 +872,6 @@ Dygraph.hsvToRGB = function (hue, saturation, value) {
  * @private
  */
 Dygraph.prototype.setColors_ = function() {
-  // TODO(danvk): compute this directly into this.attrs_['colorScheme'] and do
-  // away with this.renderOptions_.
   var num = this.attr_("labels").length - 1;
   this.colors_ = [];
   var colors = this.attr_('colors');
@@ -895,9 +894,7 @@ Dygraph.prototype.setColors_ = function() {
     }
   }
 
-  // TODO(danvk): update this w/r/t/ the new options system.
-  this.renderOptions_.colorScheme = this.colors_;
-  Dygraph.update(this.plotter_.options, this.renderOptions_);
+  this.plotter_.setColors(this.colors_);
 };
 
 /**
@@ -1681,6 +1678,9 @@ Dygraph.prototype.doUnzoom_ = function() {
     }
   }
 
+  // Clear any selection, since it's likely to be drawn in the wrong place.
+  this.clearSelection();
+
   if (dirty) {
     // Putting the drawing operation before the callback because it resets
     // yAxisRange.
@@ -2642,8 +2642,7 @@ Dygraph.prototype.predraw_ = function() {
   this.plotter_ = new DygraphCanvasRenderer(this,
                                             this.hidden_,
                                             this.hidden_ctx_,
-                                            this.layout_,
-                                            this.renderOptions_);
+                                            this.layout_);
 
   // The roller sits in the bottom left corner of the chart. We don't know where
   // this will be until the options are available, so it's positioned here.
@@ -2808,8 +2807,10 @@ Dygraph.prototype.drawGraph_ = function() {
     this.setLegendHTML_();
   } else {
     if (typeof(this.selPoints_) !== 'undefined' && this.selPoints_.length) {
-      this.lastx_ = this.selPoints_[0].xval;
-      this.updateSelection_();
+      // We should select the point nearest the page x/y here, but it's easier
+      // to just clear the selection. This prevents erroneous hover dots from
+      // being displayed.
+      this.clearSelection();
     } else {
       this.clearSelection();
     }
@@ -3316,9 +3317,10 @@ Dygraph.prototype.parseCSV_ = function(data) {
   }
 
   var start = 0;
-  if (this.labelsFromCSV_) {
+  if (!('labels' in this.user_attrs_)) {
+    // User hasn't explicitly set labels, so they're (presumably) in the CSV.
     start = 1;
-    this.attrs_.labels = lines[0].split(delim);
+    this.attrs_.labels = lines[0].split(delim);  // NOTE: _not_ user_attrs_.
   }
   var line_no = 0;
 
@@ -3734,10 +3736,20 @@ Dygraph.prototype.start_ = function() {
  * <li>errorBars: changes whether the data contains stddev</li>
  * </ul>
  *
+ * There's a huge variety of options that can be passed to this method. For a
+ * full list, see http://dygraphs.com/options.html.
+ *
  * @param {Object} attrs The new properties and values
+ * @param {Boolean} [block_redraw] Usually the chart is redrawn after every
+ * call to updateOptions(). If you know better, you can pass true to explicitly
+ * block the redraw. This can be useful for chaining updateOptions() calls,
+ * avoiding the occasional infinite loop and preventing redraws when it's not
+ * necessary (e.g. when updating a callback).
  */
-Dygraph.prototype.updateOptions = function(attrs) {
-  // TODO(danvk): this is a mess. Rethink this function.
+Dygraph.prototype.updateOptions = function(attrs, block_redraw) {
+  if (typeof(block_redraw) == 'undefined') block_redraw = false;
+
+  // TODO(danvk): this is a mess. Move these options into attr_.
   if ('rollPeriod' in attrs) {
     this.rollPeriod_ = attrs.rollPeriod;
   }
@@ -3759,15 +3771,12 @@ Dygraph.prototype.updateOptions = function(attrs) {
   // highlightCircleSize
 
   Dygraph.update(this.user_attrs_, attrs);
-  Dygraph.update(this.renderOptions_, attrs);
-
-  this.labelsFromCSV_ = (this.attr_("labels") == null);
 
   if (attrs['file']) {
     this.file_ = attrs['file'];
-    this.start_();
+    if (!block_redraw) this.start_();
   } else {
-    this.predraw_();
+    if (!block_redraw) this.predraw_();
   }
 };
 
@@ -4190,6 +4199,12 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "type": "integer",
     "description": "Width, in pixels, of the x-axis labels."
   },
+  "xAxisHeight": {
+    "default": "(null)",
+    "labels": ["Axis display"],
+    "type": "integer",
+    "description": "Height, in pixels, of the x-axis. If not set explicitly, this is computed based on axisLabelFontSize and axisTickSize."
+  },
   "showLabelsOnHighlight": {
     "default": "true",
     "labels": ["Interactive Elements", "Legend"],
@@ -4280,14 +4295,14 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
   "colorSaturation": {
     "default": "1.0",
     "labels": ["Data Series Colors"],
-    "type": "0.0 - 1.0",
+    "type": "float (0.0 - 1.0)",
     "description": "If <strong>colors</strong> is not specified, saturation of the automatically-generated data series colors."
   },
   "yAxisLabelWidth": {
     "default": "50",
     "labels": ["Axis display"],
     "type": "integer",
-    "description": "Width, in pixels, of the y-axis labels."
+    "description": "Width, in pixels, of the y-axis labels. This also affects the amount of space available for a y-axis chart label."
   },
   "hideOverlayOnMouseOut": {
     "default": "true",
@@ -4407,7 +4422,7 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
   },
   "panEdgeFraction": {
     "default": "null",
-    "labels": ["Axis Display", "Interactive Elements"],
+    "labels": ["Axis display", "Interactive Elements"],
     "type": "float",
     "default": "null",
     "description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% pased the edges of the displayed values. null means no bounds."
@@ -4454,6 +4469,66 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "type": "boolean",
     "description" : "When this option is passed to updateOptions() along with either the <code>dateWindow</code> or <code>valueRange</code> options, the zoom flags are not changed to reflect a zoomed state. This is primarily useful for when the display area of a chart is changed programmatically and also where manual zooming is allowed and use is made of the <code>isZoomed</code> method to determine this."
   },
+  "drawXGrid": {
+    "default": "true",
+    "labels": ["Grid"],
+    "type": "boolean",
+    "description" : "Whether to display vertical gridlines under the chart."
+  },
+  "drawYGrid": {
+    "default": "true",
+    "labels": ["Grid"],
+    "type": "boolean",
+    "description" : "Whether to display horizontal gridlines under the chart."
+  },
+  "drawXAxis": {
+    "default": "true",
+    "labels": ["Axis display"],
+    "type": "boolean",
+    "description" : "Whether to draw the x-axis. Setting this to false also prevents x-axis ticks from being drawn and reclaims the space for the chart grid/lines."
+  },
+  "drawYAxis": {
+    "default": "true",
+    "labels": ["Axis display"],
+    "type": "boolean",
+    "description" : "Whether to draw the y-axis. Setting this to false also prevents y-axis ticks from being drawn and reclaims the space for the chart grid/lines."
+  },
+  "gridLineWidth": {
+    "default": "0.3",
+    "labels": ["Grid"],
+    "type": "float",
+    "description" : "Thickness (in pixels) of the gridlines drawn under the chart. The vertical/horizontal gridlines can be turned off entirely by using the drawXGrid and drawYGrid options."
+  },
+  "axisLineWidth": {
+    "default": "0.3",
+    "labels": ["Axis display"],
+    "type": "float",
+    "description" : "Thickness (in pixels) of the x- and y-axis lines."
+  },
+  "axisLineColor": {
+    "default": "black",
+    "labels": ["Axis display"],
+    "type": "string",
+    "description" : "Color of the x- and y-axis lines. Accepts any value which the HTML canvas strokeStyle attribute understands, e.g. 'black' or 'rgb(0, 100, 255)'."
+  },
+  "fillAlpha": {
+    "default": "0.15",
+    "labels": ["Error Bars", "Data Series Colors"],
+    "type": "float (0.0 - 1.0)",
+    "description" : "Error bars (or custom bars) for each series are drawn in the same color as the series, but with partial transparency. This sets the transparency. A value of 0.0 means that the error bars will not be drawn, whereas a value of 1.0 means that the error bars will be as dark as the line for the series itself. This can be used to produce chart lines whose thickness varies at each point."
+  },
+  "axisLabelColor": {
+    "default": "black",
+    "labels": ["Axis display"],
+    "type": "string",
+    "description" : "Color for x- and y-axis labels. This is a CSS color string."
+  },
+  "axisLabelWidth": {
+    "default": "50",
+    "labels": ["Axis display", "Chart labels"],
+    "type": "integer",
+    "description" : "Width (in pixels) of the containing divs for x- and y-axis labels. For the y-axis, this also controls "
+  },
   "sigFigs" : {
     "default": "null",
     "labels": ["Value display/formatting"],
@@ -4471,6 +4546,12 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "labels": ["Value display/formatting"],
     "type": "integer",
     "description": "When displaying numbers in normal (not scientific) mode, large numbers will be displayed with many trailing zeros (e.g. 100000000 instead of 1e9). This can lead to unwieldy y-axis labels. If there are more than <code>maxNumberWidth</code> digits to the left of the decimal in a number, dygraphs will switch to scientific notation, even when not operating in scientific mode. If you'd like to see all those digits, set this to something large, like 20 or 30."
+  },
+  "file": {
+    "default": "(set when constructed)",
+    "labels": ["Data"],
+    "type": "string (URL of CSV or CSV), GViz DataTable or 2D Array",
+    "description": "Sets the data being displayed in the chart. This can only be set when calling updateOptions; it cannot be set from the constructor. For a full description of valid data formats, see the <a href='http://dygraphs.com/data.html'>Data Formats</a> page."
   }
 }
 ;  // </JSON>
@@ -4489,6 +4570,7 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
    'Chart labels',
    'CSV parsing',
    'Callbacks',
+   'Data',
    'Data Line display',
    'Data Series Colors',
    'Error Bars',
@@ -4516,6 +4598,7 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     var labels = op['labels'];
     if (typeof(labels) !== 'object') {
       warn('Option "' + k + '" is missing a "labels": [...] option');
+    } else {
       for (var i = 0; i < labels.length; i++) {
         if (!cats.hasOwnProperty(labels[i])) {
           warn('Option "' + k + '" has label "' + labels[i] +