update docs with temperature demo
[dygraphs.git] / dygraph.js
index c695c9d..bdfa1b1 100644 (file)
@@ -193,11 +193,11 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
 
   // Create the PlotKit grapher
   // TODO(danvk): why does the Layout need its own set of options?
-  this.layoutOptions_ = { 'errorBars': (this.attr_("errorBars") ||
-                                        this.attr_("customBars")),
-                          'xOriginIsZero': false };
+  this.layoutOptions_ = { 'xOriginIsZero': false };
   Dygraph.update(this.layoutOptions_, this.attrs_);
   Dygraph.update(this.layoutOptions_, this.user_attrs_);
+  Dygraph.update(this.layoutOptions_, {
+    'errorBars': (this.attr_("errorBars") || this.attr_("customBars")) });
 
   this.layout_ = new DygraphLayout(this, this.layoutOptions_);
 
@@ -293,10 +293,13 @@ Dygraph.prototype.createInterface_ = function() {
   enclosing.appendChild(this.graphDiv);
 
   // Create the canvas for interactive parts of the chart.
-  this.canvas_ = document.createElement("canvas");
+  // this.canvas_ = document.createElement("canvas");
+  this.canvas_ = Dygraph.createCanvas();
   this.canvas_.style.position = "absolute";
   this.canvas_.width = this.width_;
   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.
@@ -319,12 +322,15 @@ Dygraph.prototype.createInterface_ = function() {
  * @private
  */
 Dygraph.prototype.createPlotKitCanvas_ = function(canvas) {
-  var h = document.createElement("canvas");
+  // var h = document.createElement("canvas");
+  var h = Dygraph.createCanvas();
   h.style.position = "absolute";
   h.style.top = canvas.style.top;
   h.style.left = canvas.style.left;
   h.width = this.width_;
   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;
 };
@@ -578,8 +584,8 @@ Dygraph.prototype.createDragInterface_ = function() {
       if (regionWidth < 2 && regionHeight < 2 &&
           self.attr_('clickCallback') != null &&
           self.lastx_ != undefined) {
-        // TODO(danvk): pass along more info about the point.
-        self.attr_('clickCallback')(event, new Date(self.lastx_));
+        // TODO(danvk): pass along more info about the points.
+        self.attr_('clickCallback')(event, self.lastx_, self.selPoints_);
       }
 
       if (regionWidth >= 10) {
@@ -598,6 +604,7 @@ Dygraph.prototype.createDragInterface_ = function() {
 
   // Double-clicking zooms back out
   Dygraph.addEvent(this.hidden_, 'dblclick', function(event) {
+    if (self.dateWindow_ == null) return;
     self.dateWindow_ = null;
     self.drawGraph_(self.rawData_);
     var minDate = self.rawData_[0][0];
@@ -698,13 +705,17 @@ Dygraph.prototype.mouseMove_ = function(event) {
     lastx = points[points.length-1].xval;
 
   // Extract the points we've selected
-  var selPoints = [];
+  this.selPoints_ = [];
   for (var i = 0; i < points.length; i++) {
     if (points[i].xval == lastx) {
-      selPoints.push(points[i]);
+      this.selPoints_.push(points[i]);
     }
   }
 
+  if (this.attr_("highlightCallback")) {
+    this.attr_("highlightCallback")(event, lastx, this.selPoints_);
+  }
+
   // Clear the previously drawn vertical, if there is one
   var circleSize = this.attr_('highlightCircleSize');
   var ctx = this.canvas_.getContext("2d");
@@ -715,18 +726,18 @@ Dygraph.prototype.mouseMove_ = function(event) {
 
   var isOK = function(x) { return x && !isNaN(x); };
 
-  if (selPoints.length > 0) {
-    var canvasx = selPoints[0].canvasx;
+  if (this.selPoints_.length > 0) {
+    var canvasx = this.selPoints_[0].canvasx;
 
     // Set the status message to indicate the selected point(s)
     var replace = this.attr_('xValueFormatter')(lastx, this) + ":";
     var clen = this.colors_.length;
-    for (var i = 0; i < selPoints.length; i++) {
-      if (!isOK(selPoints[i].canvasy)) continue;
+    for (var i = 0; i < this.selPoints_.length; i++) {
+      if (!isOK(this.selPoints_[i].canvasy)) continue;
       if (this.attr_("labelsSeparateLines")) {
         replace += "<br/>";
       }
-      var point = selPoints[i];
+      var point = this.selPoints_[i];
       var c = new RGBColor(this.colors_[i%clen]);
       replace += " <b><font color='" + c.toHex() + "'>"
               + point.name + "</font></b>:"
@@ -739,11 +750,12 @@ Dygraph.prototype.mouseMove_ = function(event) {
 
     // Draw colored circles over the center of each selected point
     ctx.save()
-    for (var i = 0; i < selPoints.length; i++) {
-      if (!isOK(selPoints[i%clen].canvasy)) continue;
+    for (var i = 0; i < this.selPoints_.length; i++) {
+      if (!isOK(this.selPoints_[i%clen].canvasy)) continue;
       ctx.beginPath();
       ctx.fillStyle = this.colors_[i%clen];
-      ctx.arc(canvasx, selPoints[i%clen].canvasy, circleSize, 0, 360, false);
+      ctx.arc(canvasx, this.selPoints_[i%clen].canvasy, circleSize,
+              0, 2 * Math.PI, false);
       ctx.fill();
     }
     ctx.restore();
@@ -1256,16 +1268,20 @@ Dygraph.prototype.rollingAverage = function(originalData, rollPeriod) {
       var y = data[1];
       rollingData[i] = [originalData[i][0], [y, y - data[0], data[2] - y]];
 
-      low += data[0];
-      mid += y;
-      high += data[2];
-      count += 1;
+      if (y && !isNaN(y)) {
+        low += data[0];
+        mid += y;
+        high += data[2];
+        count += 1;
+      }
       if (i - rollPeriod >= 0) {
         var prev = originalData[i - rollPeriod];
-        low -= prev[1][0];
-        mid -= prev[1][1];
-        high -= prev[1][2];
-        count -= 1;
+        if (prev[1][1] && !isNaN(prev[1][1])) {
+          low -= prev[1][0];
+          mid -= prev[1][1];
+          high -= prev[1][2];
+          count -= 1;
+        }
       }
       rollingData[i] = [originalData[i][0], [ 1.0 * mid / count,
                                               1.0 * (mid - low) / count,
@@ -1708,6 +1724,21 @@ Dygraph.prototype.adjustRoll = function(length) {
   this.drawGraph_(this.rawData_);
 };
 
+/**
+ * Create a new canvas element. This is more complex than a simple
+ * document.createElement("canvas") because of IE and excanvas.
+ */
+Dygraph.createCanvas = function() {
+  var canvas = document.createElement("canvas");
+
+  isIE = (/MSIE/.test(navigator.userAgent) && !window.opera);
+  if (isIE) {
+    canvas = G_vmlCanvasManager.initElement(canvas);
+  }
+
+  return canvas;
+};
+
 
 /**
  * A wrapper around Dygraph that implements the gviz API.