X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;ds=sidebyside;f=dygraph.js;h=df41fdc2525c230cb5329d4c6179f7ec046cc8e6;hb=3df0ccf0a09d28577e3a695302f1deb926ae8a83;hp=0d77166c8591db847008fd20b706d4dfd7a11915;hpb=9a7309104212501d777d2b47b2f20f98833b9241;p=dygraphs.git
diff --git a/dygraph.js b/dygraph.js
index 0d77166..df41fdc 100644
--- a/dygraph.js
+++ b/dygraph.js
@@ -153,7 +153,6 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
this.dateWindow_ = attrs.dateWindow || null;
this.valueRange_ = attrs.valueRange || null;
this.wilsonInterval_ = attrs.wilsonInterval || true;
- this.customBars_ = attrs.customBars || false;
// Clear the div. This ensure that, if multiple dygraphs are passed the same
// div, then only one will be drawn.
@@ -193,12 +192,12 @@ 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.customBars_),
+ this.attr_("customBars")),
'xOriginIsZero': false };
MochiKit.Base.update(this.layoutOptions_, this.attrs_);
MochiKit.Base.update(this.layoutOptions_, this.user_attrs_);
- this.layout_ = new DygraphLayout(this.layoutOptions_);
+ this.layout_ = new DygraphLayout(this, this.layoutOptions_);
// TODO(danvk): why does the Renderer need its own set of options?
this.renderOptions_ = { colorScheme: this.colors_,
@@ -206,7 +205,8 @@ Dygraph.prototype.__init__ = function(div, file, attrs) {
axisLineWidth: Dygraph.AXIS_LINE_WIDTH };
MochiKit.Base.update(this.renderOptions_, this.attrs_);
MochiKit.Base.update(this.renderOptions_, this.user_attrs_);
- this.plotter_ = new DygraphCanvasRenderer(this.hidden_, this.layout_,
+ this.plotter_ = new DygraphCanvasRenderer(this,
+ this.hidden_, this.layout_,
this.renderOptions_);
this.createStatusMessage_();
@@ -353,6 +353,34 @@ Dygraph.prototype.setColors_ = function() {
MochiKit.Base.update(this.layoutOptions_, this.attrs_);
}
+// The following functions are from quirksmode.org
+// http://www.quirksmode.org/js/findpos.html
+Dygraph.findPosX = function(obj) {
+ var curleft = 0;
+ if (obj.offsetParent) {
+ while (obj.offsetParent) {
+ curleft += obj.offsetLeft;
+ obj = obj.offsetParent;
+ }
+ }
+ else if (obj.x)
+ curleft += obj.x;
+ return curleft;
+};
+
+Dygraph.findPosY = function(obj) {
+ var curtop = 0;
+ if (obj.offsetParent) {
+ while (obj.offsetParent) {
+ curtop += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ }
+ else if (obj.y)
+ curtop += obj.y;
+ return curtop;
+};
+
/**
* Create the div that contains information on the selected point(s)
* This goes in the top right of the canvas, unless an external div has already
@@ -439,8 +467,8 @@ Dygraph.prototype.createDragInterface_ = function() {
// Track the beginning of drag events
connect(this.hidden_, 'onmousedown', function(event) {
mouseDown = true;
- px = PlotKit.Base.findPosX(self.canvas_);
- py = PlotKit.Base.findPosY(self.canvas_);
+ px = Dygraph.findPosX(self.canvas_);
+ py = Dygraph.findPosY(self.canvas_);
dragStartX = getX(event);
dragStartY = getY(event);
});
@@ -574,7 +602,7 @@ Dygraph.prototype.doZoom_ = function(lowX, highX) {
* @private
*/
Dygraph.prototype.mouseMove_ = function(event) {
- var canvasx = event.mouse().page.x - PlotKit.Base.findPosX(this.hidden_);
+ var canvasx = event.mouse().page.x - Dygraph.findPosX(this.hidden_);
var points = this.layout_.points;
var lastx = -1;
@@ -611,6 +639,8 @@ Dygraph.prototype.mouseMove_ = function(event) {
ctx.clearRect(px - circleSize - 1, 0, 2 * circleSize + 2, this.height_);
}
+ var isOK = function(x) { return x && !isNaN(x); };
+
if (selPoints.length > 0) {
var canvasx = selPoints[0].canvasx;
@@ -618,7 +648,7 @@ Dygraph.prototype.mouseMove_ = function(event) {
var replace = this.attr_('xValueFormatter')(lastx, this) + ":";
var clen = this.colors_.length;
for (var i = 0; i < selPoints.length; i++) {
- if (isNaN(selPoints[i].canvasy)) continue;
+ if (!isOK(selPoints[i].canvasy)) continue;
if (this.attr_("labelsSeparateLines")) {
replace += "
";
}
@@ -635,7 +665,7 @@ 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 (isNaN(selPoints[i%clen].canvasy)) continue;
+ if (!isOK(selPoints[i%clen].canvasy)) continue;
ctx.beginPath();
ctx.fillStyle = this.colors_[i%clen].toRGBString();
ctx.arc(canvasx, selPoints[i%clen].canvasy, circleSize, 0, 360, false);
@@ -960,6 +990,46 @@ Dygraph.prototype.addYTicks_ = function(minY, maxY) {
yTicks: ticks } );
};
+// Computes the range of the data series (including confidence intervals).
+// series is either [ [x1, y1], [x2, y2], ... ] or
+// [ [x1, [y1, dev_low, dev_high]], [x2, [y2, dev_low, dev_high]], ...
+// Returns [low, high]
+Dygraph.prototype.extremeValues_ = function(series) {
+ var minY = null, maxY = null;
+
+ var bars = this.attr_("errorBars") || this.attr_("customBars");
+ if (bars) {
+ // With custom bars, maxY is the max of the high values.
+ for (var j = 0; j < series.length; j++) {
+ var y = series[j][1][0];
+ if (!y) continue;
+ var low = y - series[j][1][1];
+ var high = y + series[j][1][2];
+ if (low > y) low = y; // this can happen with custom bars,
+ if (high < y) high = y; // e.g. in tests/custom-bars.html
+ if (maxY == null || high > maxY) {
+ maxY = high;
+ }
+ if (minY == null || low < minY) {
+ minY = low;
+ }
+ }
+ } else {
+ for (var j = 0; j < series.length; j++) {
+ var y = series[j][1];
+ if (!y) continue;
+ if (maxY == null || y > maxY) {
+ maxY = y;
+ }
+ if (minY == null || y < minY) {
+ minY = y;
+ }
+ }
+ }
+
+ return [minY, maxY];
+};
+
/**
* Update the graph with new data. Data is in the format
* [ [date1, val1, val2, ...], [date2, val1, val2, ...] if errorBars=false
@@ -972,6 +1042,7 @@ Dygraph.prototype.drawGraph_ = function(data) {
var minY = null, maxY = null;
this.layout_.removeAllDatasets();
this.setColors_();
+ this.attrs_['pointSize'] = 0.5 * this.attr_('highlightCircleSize');
// Loop over all fields in the dataset
for (var i = 1; i < data[0].length; i++) {
@@ -983,7 +1054,7 @@ Dygraph.prototype.drawGraph_ = function(data) {
series = this.rollingAverage(series, this.rollPeriod_);
// Prune down to the desired range, if necessary (for zooming)
- var bars = this.attr_("errorBars") || this.customBars_;
+ var bars = this.attr_("errorBars") || this.attr_("customBars");
if (this.dateWindow_) {
var low = this.dateWindow_[0];
var high= this.dateWindow_[1];
@@ -991,39 +1062,17 @@ Dygraph.prototype.drawGraph_ = function(data) {
for (var k = 0; k < series.length; k++) {
if (series[k][0] >= low && series[k][0] <= high) {
pruned.push(series[k]);
- var y = bars ? series[k][1][0] : series[k][1];
- if (maxY == null || y > maxY) maxY = y;
- if (minY == null || y < minY) minY = y;
}
}
series = pruned;
- } else {
- if (!this.customBars_) {
- for (var j = 0; j < series.length; j++) {
- var y = bars ? series[j][1][0] : series[j][1];
- if (maxY == null || y > maxY) {
- maxY = bars ? y + series[j][1][1] : y;
- }
- if (minY == null || y < minY) {
- minY = bars ? y + series[j][1][1] : y;
- }
- }
- } else {
- // With custom bars, maxY is the max of the high values.
- for (var j = 0; j < series.length; j++) {
- var y = series[j][1][0];
- var high = series[j][1][2];
- if (high > y) y = high;
- if (maxY == null || y > maxY) {
- maxY = y;
- }
- if (minY == null || y < minY) {
- minY = y;
- }
- }
- }
}
+ var extremes = this.extremeValues_(series);
+ var thisMinY = extremes[0];
+ var thisMaxY = extremes[1];
+ if (!minY || thisMinY < minY) minY = thisMinY;
+ if (!maxY || thisMaxY > maxY) maxY = thisMaxY;
+
if (bars) {
var vals = [];
for (var j=0; j