Merge branch 'master' into per_series
[dygraphs.git] / dygraph.js
index b53dccf..517f0c6 100644 (file)
@@ -240,8 +240,12 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
   this.start_();
 };
 
-Dygraph.prototype.attr_ = function(name) {
-  if (typeof(this.user_attrs_[name]) != 'undefined') {
+Dygraph.prototype.attr_ = function(name, series) {
+  if (series &&
+      typeof(this.user_attrs_[series]) != 'undefined' &&
+      typeof(this.user_attrs_[series][name]) != 'undefined') {
+    return this.user_attrs_[series][name];
+  } else if (typeof(this.user_attrs_[name]) != 'undefined') {
     return this.user_attrs_[name];
   } else if (typeof(this.attrs_[name]) != 'undefined') {
     return this.attrs_[name];
@@ -352,6 +356,32 @@ Dygraph.prototype.toDataCoords = function(x, y) {
   return ret;
 };
 
+/**
+ * Returns the number of columns (including the independent variable).
+ */
+Dygraph.prototype.numColumns = function() {
+  return this.rawData_[0].length;
+};
+
+/**
+ * Returns the number of rows (excluding any header/label row).
+ */
+Dygraph.prototype.numRows = function() {
+  return this.rawData_.length;
+};
+
+/**
+ * Returns the value in the given row and column. If the row and column exceed
+ * the bounds on the data, returns null. Also returns null if the value is
+ * missing.
+ */
+Dygraph.prototype.getValue = function(row, col) {
+  if (row < 0 || row > this.rawData_.length) return null;
+  if (col < 0 || col > this.rawData_[row].length) return null;
+
+  return this.rawData_[row][col];
+};
+
 Dygraph.addEvent = function(el, evt, fn) {
   var normed_fn = function(e) {
     if (!e) var e = window.event;
@@ -1011,7 +1041,7 @@ Dygraph.prototype.updateSelection_ = function() {
     if (this.attr_('showLabelsOnHighlight')) {
       // Set the status message to indicate the selected point(s)
       for (var i = 0; i < this.selPoints_.length; i++) {
-       if (!this.attr_("labelsShowZeroValues") && this.selPoints_[i].yval == 0) continue;        
+        if (!this.attr_("labelsShowZeroValues") && this.selPoints_[i].yval == 0) continue;
         if (!isOK(this.selPoints_[i].canvasy)) continue;
         if (this.attr_("labelsSeparateLines")) {
           replace += "<br/>";
@@ -1555,8 +1585,6 @@ Dygraph.prototype.drawGraph_ = function(data) {
   this.setColors_();
   this.attrs_['pointSize'] = 0.5 * this.attr_('highlightCircleSize');
 
-  var connectSeparatedPoints = this.attr_('connectSeparatedPoints');
-
   // Loop over the fields (series).  Go from the last to the first,
   // because if they're stacked that's how we accumulate the values.
 
@@ -1567,6 +1595,8 @@ Dygraph.prototype.drawGraph_ = function(data) {
   for (var i = data[0].length - 1; i >= 1; i--) {
     if (!this.visibility()[i - 1]) continue;
 
+    var connectSeparatedPoints = this.attr_('connectSeparatedPoints', i);
+
     var series = [];
     for (var j = 0; j < data.length; j++) {
       if (data[j][i] != null || !connectSeparatedPoints) {
@@ -2122,8 +2152,8 @@ Dygraph.prototype.parseDataTable_ = function(data) {
     var row = [];
     if (typeof(data.getValue(i, 0)) === 'undefined' ||
         data.getValue(i, 0) === null) {
-      this.warning("Ignoring row " + i +
-                   " of DataTable because of undefined or null first column.");
+      this.warn("Ignoring row " + i +
+                " of DataTable because of undefined or null first column.");
       continue;
     }
 
@@ -2280,6 +2310,9 @@ Dygraph.prototype.updateOptions = function(attrs) {
   if (attrs.valueRange) {
     this.valueRange_ = attrs.valueRange;
   }
+
+  // TODO(danvk): validate per-series options.
+
   Dygraph.update(this.user_attrs_, attrs);
   Dygraph.update(this.renderOptions_, attrs);