gviz mostly working
authorDan Vanderkam <danvdk@gmail.com>
Sat, 11 Sep 2010 17:46:01 +0000 (10:46 -0700)
committerDan Vanderkam <danvdk@gmail.com>
Sat, 11 Sep 2010 17:46:01 +0000 (10:46 -0700)
dygraph-canvas.js
dygraph.js
tests/annotation-gviz.html [new file with mode: 0644]

index b71044a..13e5fe6 100644 (file)
@@ -30,14 +30,13 @@ DygraphLayout.prototype.addDataset = function(setname, set_xy) {
   this.datasets[setname] = set_xy;
 };
 
-// TODO(danvk): CONTRACT remove
 DygraphLayout.prototype.setAnnotations = function(ann) {
   // The Dygraph object's annotations aren't parsed. We parse them here and
   // save a copy.
   var parse = this.attr_('xValueParser');
   for (var i = 0; i < ann.length; i++) {
     var a = {};
-    if (!ann[i].x) {
+    if (!ann[i].xval && !ann[i].x) {
       this.dygraph_.error("Annotations must have an 'x' property");
       return;
     }
@@ -49,7 +48,7 @@ DygraphLayout.prototype.setAnnotations = function(ann) {
       return;
     }
     Dygraph.update(a, ann[i]);
-    a.xval = parse(a.x);
+    if (!a.xval) a.xval = parse(a.x);
     this.annotations.push(a);
   }
 };
index fed7056..e8afb2b 100644 (file)
@@ -2024,7 +2024,7 @@ Dygraph.prototype.parseArray_ = function(data) {
  * The data is expected to have a first column that is either a date or a
  * number. All subsequent columns must be numbers. If there is a clear mismatch
  * between this.xValueParser_ and the type of the first column, it will be
- * fixed. Returned value is in the same format as return value of parseCSV_.
+ * fixed. Fills out rawData_.
  * @param {Array.<Object>} data See above.
  * @private
  */
@@ -2032,15 +2032,6 @@ Dygraph.prototype.parseDataTable_ = function(data) {
   var cols = data.getNumberOfColumns();
   var rows = data.getNumberOfRows();
 
-  // Read column labels
-  var labels = [];
-  for (var i = 0; i < cols; i++) {
-    labels.push(data.getColumnLabel(i));
-    if (i != 0 && this.attr_("errorBars")) i += 1;
-  }
-  this.attrs_.labels = labels;
-  cols = labels.length;
-
   var indepType = data.getColumnType(0);
   if (indepType == 'date' || indepType == 'datetime') {
     this.attrs_.xValueFormatter = Dygraph.dateString_;
@@ -2058,8 +2049,41 @@ Dygraph.prototype.parseDataTable_ = function(data) {
     return null;
   }
 
+  // Array of the column indices which contain data (and not annotations).
+  var colIdx = [];
+  var annotationCols = {};  // data index -> [annotation cols]
+  var hasAnnotations = false;
+  for (var i = 1; i < cols; i++) {
+    var type = data.getColumnType(i);
+    if (type == 'number') {
+      colIdx.push(i);
+    } else if (type == 'string' && this.attr_('displayAnnotations')) {
+      // This is OK -- it's an annotation column.
+      var dataIdx = colIdx[colIdx.length - 1];
+      if (!annotationCols.hasOwnProperty(dataIdx)) {
+        annotationCols[dataIdx] = [i];
+      } else {
+        annotationCols[dataIdx].push(i);
+      }
+      hasAnnotations = true;
+    } else {
+      this.error("Only 'number' is supported as a dependent type with Gviz." +
+                 " 'string' is only supported if displayAnnotations is true");
+    }
+  }
+
+  // Read column labels
+  // TODO(danvk): add support back for errorBars
+  var labels = [data.getColumnLabel(0)];
+  for (var i = 0; i < colIdx.length; i++) {
+    labels.push(data.getColumnLabel(colIdx[i]));
+  }
+  this.attrs_.labels = labels;
+  cols = labels.length;
+
   var ret = [];
   var outOfOrder = false;
+  var annotations = [];
   for (var i = 0; i < rows; i++) {
     var row = [];
     if (typeof(data.getValue(i, 0)) === 'undefined' ||
@@ -2075,8 +2099,23 @@ Dygraph.prototype.parseDataTable_ = function(data) {
       row.push(data.getValue(i, 0));
     }
     if (!this.attr_("errorBars")) {
-      for (var j = 1; j < cols; j++) {
-        row.push(data.getValue(i, j));
+      for (var j = 0; j < colIdx.length; j++) {
+        var col = colIdx[j];
+        row.push(data.getValue(i, col));
+        if (hasAnnotations &&
+            annotationCols.hasOwnProperty(col) &&
+            data.getValue(i, annotationCols[col][0]) != null) {
+          var ann = {};
+          ann.series = data.getColumnLabel(col);
+          ann.xval = row[0];
+          ann.shortText = String.fromCharCode(65 /* A */ + annotations.length)
+          ann.text = '';
+          for (var k = 0; k < annotationCols[col].length; k++) {
+            if (k) ann.text += "\n";
+            ann.text += data.getValue(i, annotationCols[col][k]);
+          }
+          annotations.push(ann);
+        }
       }
     } else {
       for (var j = 0; j < cols - 1; j++) {
@@ -2093,7 +2132,11 @@ Dygraph.prototype.parseDataTable_ = function(data) {
     this.warn("DataTable is out of order; order it correctly to speed loading.");
     ret.sort(function(a,b) { return a[0] - b[0] });
   }
-  return ret;
+  this.rawData_ = ret;
+
+  if (annotations.length > 0) {
+    this.setAnnotations(annotations, true);
+  }
 }
 
 // These functions are all based on MochiKit.
@@ -2159,7 +2202,7 @@ Dygraph.prototype.start_ = function() {
   } else if (typeof this.file_ == 'object' &&
              typeof this.file_.getColumnRange == 'function') {
     // must be a DataTable from gviz.
-    this.rawData_ = this.parseDataTable_(this.file_);
+    this.parseDataTable_(this.file_);
     this.drawGraph_(this.rawData_);
   } else if (typeof this.file_ == 'string') {
     // Heuristic: a newline means it's CSV data. Otherwise it's an URL.
@@ -2302,10 +2345,12 @@ Dygraph.prototype.setVisibility = function(num, value) {
 /**
  * Update the list of annotations and redraw the chart.
  */
-Dygraph.prototype.setAnnotations = function(ann) {
+Dygraph.prototype.setAnnotations = function(ann, suppressDraw) {
   this.annotations_ = ann;
   this.layout_.setAnnotations(this.annotations_);
-  this.drawGraph_(this.rawData_);
+  if (!suppressDraw) {
+    this.drawGraph_(this.rawData_);
+  }
 };
 
 /**
@@ -2319,7 +2364,6 @@ Dygraph.addAnnotationRule = function() {
   if (Dygraph.addedAnnotationCSS) return;
 
   var mysheet=document.styleSheets[0]
-  var totalrules=mysheet.cssRules? mysheet.cssRules.length : mysheet.rules.length
   var rule = "border: 1px solid black; " +
              "background-color: white; " +
              "text-align: center;";
diff --git a/tests/annotation-gviz.html b/tests/annotation-gviz.html
new file mode 100644 (file)
index 0000000..bfb3daa
--- /dev/null
@@ -0,0 +1,47 @@
+<html>
+  <head>
+    <script type="text/javascript" src="../strftime/strftime-min.js"></script>
+    <script type="text/javascript" src="../rgbcolor/rgbcolor.js"></script>
+    <script type="text/javascript" src="../dygraph-canvas.js"></script>
+    <script type="text/javascript" src="../dygraph.js"></script>
+
+    <script type='text/javascript' src='http://www.google.com/jsapi'></script>
+    <script type='text/javascript'>
+      google.load('visualization', '1', {'packages':['annotatedtimeline']});
+      google.setOnLoadCallback(drawChart);
+      function drawChart() {
+        var data = new google.visualization.DataTable();
+        data.addColumn('date', 'Date');
+        data.addColumn('number', 'Sold Pencils');
+        data.addColumn('string', 'title1');
+        data.addColumn('string', 'text1');
+        data.addColumn('number', 'Sold Pens');
+        data.addColumn('string', 'title2');
+        data.addColumn('string', 'text2');
+        data.addRows([
+          [new Date(2008, 1 ,1), 30000, undefined, undefined, 40645, undefined, undefined],
+          [new Date(2008, 1 ,2), 14045, undefined, undefined, 20374, undefined, undefined],
+          [new Date(2008, 1 ,3), 55022, undefined, undefined, 50766, undefined, undefined],
+          [new Date(2008, 1 ,4), 75284, undefined, undefined, 14334, 'Out of Stock','Ran out of stock on pens at 4pm'],
+          [new Date(2008, 1 ,5), 41476, 'Bought Pens','Bought 200k pens', 66467, undefined, undefined],
+          [new Date(2008, 1 ,6), 33322, undefined, undefined, 39463, undefined, undefined]
+        ]);
+
+        var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('gviz_div'));
+        chart.draw(data, {displayAnnotations: true});
+
+        var g = new Dygraph.GVizChart(document.getElementById("dg_div"));
+        g.draw(data, {displayAnnotations: true, labelsKMB: true});
+      }
+    </script>
+  </head>
+
+  <body>
+    <h3>Google AnnotatedTimeline:</h3>
+    <div id='gviz_div' style='width: 700px; height: 240px;'></div>
+
+    <h3>Dygraph.GVizChart:</h3>
+    <div id='dg_div' style='width: 700px; height: 240px;'></div>
+  </body>
+</html>
+