update symlinks
[dygraphs.git] / dygraph.js
index 8b5124d..f940cad 100644 (file)
@@ -105,6 +105,8 @@ Dygraph.DEFAULT_ATTRS = {
   xValueParser: Dygraph.dateParser,
   xTicker: Dygraph.dateTicker,
 
+  delimiter: ',',
+
   sigma: 2.0,
   errorBars: false,
   fractions: false,
@@ -125,7 +127,7 @@ Dygraph.prototype.__old_init__ = function(div, file, labels, attrs) {
   if (labels != null) {
     var new_labels = ["Date"];
     for (var i = 0; i < labels.length; i++) new_labels.push(labels[i]);
-    MochiKit.Base.update(attrs, { 'labels': new_labels });
+    Dygraph.update(attrs, { 'labels': new_labels });
   }
   this.__init__(div, file, attrs);
 };
@@ -178,10 +180,10 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
   // user_attrs_ and then computed attrs_. This way Dygraphs can set intelligent
   // defaults without overriding behavior that the user specifically asks for.
   this.user_attrs_ = {};
-  MochiKit.Base.update(this.user_attrs_, attrs);
+  Dygraph.update(this.user_attrs_, attrs);
 
   this.attrs_ = {};
-  MochiKit.Base.update(this.attrs_, Dygraph.DEFAULT_ATTRS);
+  Dygraph.update(this.attrs_, Dygraph.DEFAULT_ATTRS);
 
   // Make a note of whether labels will be pulled from the CSV file.
   this.labelsFromCSV_ = (this.attr_("labels") == null);
@@ -194,8 +196,8 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
   this.layoutOptions_ = { 'errorBars': (this.attr_("errorBars") ||
                                         this.attr_("customBars")),
                           'xOriginIsZero': false };
-  MochiKit.Base.update(this.layoutOptions_, this.attrs_);
-  MochiKit.Base.update(this.layoutOptions_, this.user_attrs_);
+  Dygraph.update(this.layoutOptions_, this.attrs_);
+  Dygraph.update(this.layoutOptions_, this.user_attrs_);
 
   this.layout_ = new DygraphLayout(this, this.layoutOptions_);
 
@@ -203,8 +205,8 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
   this.renderOptions_ = { colorScheme: this.colors_,
                           strokeColor: null,
                           axisLineWidth: Dygraph.AXIS_LINE_WIDTH };
-  MochiKit.Base.update(this.renderOptions_, this.attrs_);
-  MochiKit.Base.update(this.renderOptions_, this.user_attrs_);
+  Dygraph.update(this.renderOptions_, this.attrs_);
+  Dygraph.update(this.renderOptions_, this.user_attrs_);
   this.plotter_ = new DygraphCanvasRenderer(this,
                                             this.hidden_, this.layout_,
                                             this.renderOptions_);
@@ -388,9 +390,9 @@ Dygraph.prototype.setColors_ = function() {
 
   // TODO(danvk): update this w/r/t/ the new options system. 
   this.renderOptions_.colorScheme = this.colors_;
-  MochiKit.Base.update(this.plotter_.options, this.renderOptions_);
-  MochiKit.Base.update(this.layoutOptions_, this.user_attrs_);
-  MochiKit.Base.update(this.layoutOptions_, this.attrs_);
+  Dygraph.update(this.plotter_.options, this.renderOptions_);
+  Dygraph.update(this.layoutOptions_, this.user_attrs_);
+  Dygraph.update(this.layoutOptions_, this.attrs_);
 }
 
 // The following functions are from quirksmode.org
@@ -440,7 +442,7 @@ Dygraph.prototype.createStatusMessage_ = function(){
       "background": "white",
       "textAlign": "left",
       "overflow": "hidden"};
-    MochiKit.Base.update(messagestyle, this.attr_('labelsDivStyles'));
+    Dygraph.update(messagestyle, this.attr_('labelsDivStyles'));
     var div = document.createElement("div");
     for (var name in messagestyle) {
       div.style[name] = messagestyle[name];
@@ -576,8 +578,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) {
@@ -596,6 +598,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];
@@ -696,13 +699,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");
@@ -713,18 +720,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>:"
@@ -737,11 +744,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, 360, false);
       ctx.fill();
     }
     ctx.restore();
@@ -1402,10 +1410,17 @@ Dygraph.prototype.detectTypeFromString_ = function(str) {
 Dygraph.prototype.parseCSV_ = function(data) {
   var ret = [];
   var lines = data.split("\n");
+
+  // Use the default delimiter or fall back to a tab if that makes sense.
+  var delim = this.attr_('delimiter');
+  if (lines[0].indexOf(delim) == -1 && lines[0].indexOf('\t') >= 0) {
+    delim = '\t';
+  }
+
   var start = 0;
   if (this.labelsFromCSV_) {
     start = 1;
-    this.attrs_.labels = lines[0].split(",");
+    this.attrs_.labels = lines[0].split(delim);
   }
 
   var xParser;
@@ -1414,7 +1429,8 @@ Dygraph.prototype.parseCSV_ = function(data) {
   for (var i = start; i < lines.length; i++) {
     var line = lines[i];
     if (line.length == 0) continue;  // skip blank lines
-    var inFields = line.split(',');
+    if (line[0] == '#') continue;    // skip comment lines
+    var inFields = line.split(delim);
     if (inFields.length < 2) continue;
 
     var fields = [];
@@ -1570,6 +1586,15 @@ Dygraph.prototype.parseDataTable_ = function(data) {
 }
 
 // These functions are all based on MochiKit.
+Dygraph.update = function (self, o) {
+  if (typeof(o) != 'undefined' && o !== null) {
+    for (var k in o) {
+      self[k] = o[k];
+    }
+  }
+  return self;
+};
+
 Dygraph.isArrayLike = function (o) {
   var typ = typeof(o);
   if (
@@ -1665,7 +1690,7 @@ Dygraph.prototype.updateOptions = function(attrs) {
   if (attrs.valueRange) {
     this.valueRange_ = attrs.valueRange;
   }
-  MochiKit.Base.update(this.user_attrs_, attrs);
+  Dygraph.update(this.user_attrs_, attrs);
 
   this.labelsFromCSV_ = (this.attr_("labels") == null);