X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=8d5d3698da6ebd35a6e938d71bcefe98f82604c4;hb=0af6e3468086533368de97dc6ea704df5ce3ef10;hp=c695c9d5eecc218ff2a3086c26beb9f66222dfab;hpb=3d67f03bae2df09cb81a49ad8212bbc855b30b25;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index c695c9d..8d5d369 100644 --- a/dygraph.js +++ b/dygraph.js @@ -91,6 +91,7 @@ Dygraph.DEFAULT_ATTRS = { }, labelsSeparateLines: false, labelsKMB: false, + labelsKMG2: false, strokeWidth: 1.0, @@ -193,11 +194,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 +294,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 +323,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; }; @@ -445,7 +452,9 @@ Dygraph.prototype.createStatusMessage_ = function(){ Dygraph.update(messagestyle, this.attr_('labelsDivStyles')); var div = document.createElement("div"); for (var name in messagestyle) { - div.style[name] = messagestyle[name]; + if (messagestyle.hasOwnProperty(name)) { + div.style[name] = messagestyle[name]; + } } this.graphDiv.appendChild(div); this.attrs_.labelsDiv = div; @@ -470,7 +479,9 @@ Dygraph.prototype.createRollInterface_ = function() { roller.size = "2"; roller.value = this.rollPeriod_; for (var name in textAttr) { - roller.style[name] = textAttr[name]; + if (textAttr.hasOwnProperty(name)) { + roller.style[name] = textAttr[name]; + } } var pa = this.graphDiv; @@ -578,8 +589,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 +609,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 +710,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 +731,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 += "
"; } - var point = selPoints[i]; + var point = this.selPoints_[i]; var c = new RGBColor(this.colors_[i%clen]); replace += " " + point.name + ":" @@ -739,11 +755,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(); @@ -1035,16 +1052,26 @@ Dygraph.numericTicks = function(minV, maxV, self) { var ticks = []; for (var i = 0; i < nTicks; i++) { var tickV = low_val + i * scale; + var absTickV = Math.abs(tickV); var label = self.round_(tickV, 2); if (self.attr_("labelsKMB")) { var k = 1000; - if (tickV >= k*k*k) { + if (absTickV >= k*k*k) { label = self.round_(tickV/(k*k*k), 1) + "B"; - } else if (tickV >= k*k) { + } else if (absTickV >= k*k) { label = self.round_(tickV/(k*k), 1) + "M"; - } else if (tickV >= k) { + } else if (absTickV >= k) { label = self.round_(tickV/k, 1) + "K"; } + } else if (self.attr_("labelsKMG2")) { + var k = 1024; + if (absTickV >= k*k*k) { + label = self.round_(tickV/(k*k*k), 1) + "G"; + } else if (absTickV >= k*k) { + label = self.round_(tickV/(k*k), 1) + "M"; + } else if (absTickV >= k) { + label = self.round_(tickV/k, 1) + "k"; + } } ticks.push( {label: label, v: tickV} ); } @@ -1256,16 +1283,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 != null && !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] != null && !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, @@ -1285,7 +1316,7 @@ Dygraph.prototype.rollingAverage = function(originalData, rollPeriod) { var num_ok = 0; for (var j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) { var y = originalData[j][1]; - if (!y || isNaN(y)) continue; + if (y == null || isNaN(y)) continue; num_ok++; sum += originalData[j][1]; } @@ -1303,7 +1334,7 @@ Dygraph.prototype.rollingAverage = function(originalData, rollPeriod) { var num_ok = 0; for (var j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) { var y = originalData[j][1][0]; - if (!y || isNaN(y)) continue; + if (y == null || isNaN(y)) continue; num_ok++; sum += originalData[j][1][0]; variance += Math.pow(originalData[j][1][1], 2); @@ -1544,8 +1575,10 @@ Dygraph.prototype.parseDataTable_ = function(data) { 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') { @@ -1571,8 +1604,14 @@ Dygraph.prototype.parseDataTable_ = function(data) { } else { row.push(data.getValue(i, 0)); } - for (var j = 1; j < cols; j++) { - row.push(data.getValue(i, j)); + if (!this.attr_("errorBars")) { + for (var j = 1; j < cols; j++) { + row.push(data.getValue(i, j)); + } + } else { + for (var j = 0; j < cols - 1; j++) { + row.push([ data.getValue(i, 1 + 2 * j), data.getValue(i, 2 + 2 * j) ]); + } } ret.push(row); } @@ -1583,7 +1622,9 @@ Dygraph.prototype.parseDataTable_ = function(data) { Dygraph.update = function (self, o) { if (typeof(o) != 'undefined' && o !== null) { for (var k in o) { - self[k] = o[k]; + if (o.hasOwnProperty(k)) { + self[k] = o[k]; + } } } return self; @@ -1708,6 +1749,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.