X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=fed7056f71a5409ca56ba46684d773fa55b68193;hb=ab5e5c7548f975820f6b469886d15ff5bc1b8477;hp=dc4ff2bb96855de4e867a37167b425da9f797dbf;hpb=61b78cd6890c539c2931ce94f2b6cac320b2d8c9;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index dc4ff2b..fed7056 100644 --- a/dygraph.js +++ b/dygraph.js @@ -123,7 +123,9 @@ Dygraph.DEFAULT_ATTRS = { connectSeparatedPoints: false, stackedGraph: false, - hideOverlayOnMouseOut: true + hideOverlayOnMouseOut: true, + + stepPlot: false }; // Various logging levels. @@ -132,6 +134,9 @@ Dygraph.INFO = 2; Dygraph.WARNING = 3; Dygraph.ERROR = 3; +// Used for initializing annotation CSS rules only once. +Dygraph.addedAnnotationCSS = false; + Dygraph.prototype.__old_init__ = function(div, file, labels, attrs) { // Labels is no longer a constructor parameter, since it's typically set // directly from the data source. It also conains a name for the x-axis, @@ -168,6 +173,7 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { this.valueRange_ = attrs.valueRange || null; this.wilsonInterval_ = attrs.wilsonInterval || true; this.is_initial_draw_ = true; + this.annotations_ = []; // Clear the div. This ensure that, if multiple dygraphs are passed the same // div, then only one will be drawn. @@ -186,11 +192,17 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { // The div might have been specified as percent of the current window size, // convert that to an appropriate number of pixels. if (div.style.width.indexOf("%") == div.style.width.length - 1) { - // Minus ten pixels keeps scrollbars from showing up for a 100% width div. - this.width_ = (this.width_ * self.innerWidth / 100) - 10; + this.width_ = div.offsetWidth; } if (div.style.height.indexOf("%") == div.style.height.length - 1) { - this.height_ = (this.height_ * self.innerHeight / 100) - 10; + this.height_ = div.offsetHeight; + } + + if (this.width_ == 0) { + this.error("dygraph has zero width. Please specify a width in pixels."); + } + if (this.height_ == 0) { + this.error("dygraph has zero height. Please specify a height in pixels."); } // TODO(danvk): set fillGraph to be part of attrs_ here, not user_attrs_. @@ -219,6 +231,8 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { // Make a note of whether labels will be pulled from the CSV file. this.labelsFromCSV_ = (this.attr_("labels") == null); + Dygraph.addAnnotationRule(); + // Create the containing DIV and other interactive elements this.createInterface_(); @@ -387,20 +401,24 @@ Dygraph.prototype.createInterface_ = function() { 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. this.hidden_ = this.createPlotKitCanvas_(this.canvas_); + // The interactive parts of the graph are drawn on top of the chart. + this.graphDiv.appendChild(this.hidden_); + this.graphDiv.appendChild(this.canvas_); + this.mouseEventElement_ = this.canvas_; + // Make sure we don't overdraw. Dygraph.clipCanvas_(this.hidden_, this.clippingArea_); Dygraph.clipCanvas_(this.canvas_, this.clippingArea_); var dygraph = this; - Dygraph.addEvent(this.hidden_, 'mousemove', function(e) { + Dygraph.addEvent(this.mouseEventElement_, 'mousemove', function(e) { dygraph.mouseMove_(e); }); - Dygraph.addEvent(this.hidden_, 'mouseout', function(e) { + Dygraph.addEvent(this.mouseEventElement_, 'mouseout', function(e) { dygraph.mouseOut_(e); }); @@ -476,7 +494,6 @@ Dygraph.prototype.createPlotKitCanvas_ = function(canvas) { 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; }; @@ -707,7 +724,7 @@ Dygraph.prototype.createDragInterface_ = function() { var getY = function(e) { return Dygraph.pageX(e) - py }; // Draw zoom rectangles when the mouse is down and the user moves around - Dygraph.addEvent(this.hidden_, 'mousemove', function(event) { + Dygraph.addEvent(this.mouseEventElement_, 'mousemove', function(event) { if (isZooming) { dragEndX = getX(event); dragEndY = getY(event); @@ -729,7 +746,7 @@ Dygraph.prototype.createDragInterface_ = function() { }); // Track the beginning of drag events - Dygraph.addEvent(this.hidden_, 'mousedown', function(event) { + Dygraph.addEvent(this.mouseEventElement_, 'mousedown', function(event) { px = Dygraph.findPosX(self.canvas_); py = Dygraph.findPosY(self.canvas_); dragStartX = getX(event); @@ -763,7 +780,7 @@ Dygraph.prototype.createDragInterface_ = function() { }); // Temporarily cancel the dragging event when the mouse leaves the graph - Dygraph.addEvent(this.hidden_, 'mouseout', function(event) { + Dygraph.addEvent(this.mouseEventElement_, 'mouseout', function(event) { if (isZooming) { dragEndX = null; dragEndY = null; @@ -772,7 +789,7 @@ Dygraph.prototype.createDragInterface_ = function() { // If the mouse is released on the canvas during a drag event, then it's a // zoom. Only do the zoom if it's over a large enough area (>= 10 pixels) - Dygraph.addEvent(this.hidden_, 'mouseup', function(event) { + Dygraph.addEvent(this.mouseEventElement_, 'mouseup', function(event) { if (isZooming) { isZooming = false; dragEndX = getX(event); @@ -808,7 +825,7 @@ Dygraph.prototype.createDragInterface_ = function() { }); // Double-clicking zooms back out - Dygraph.addEvent(this.hidden_, 'dblclick', function(event) { + Dygraph.addEvent(this.mouseEventElement_, 'dblclick', function(event) { if (self.dateWindow_ == null) return; self.dateWindow_ = null; self.drawGraph_(self.rawData_); @@ -879,7 +896,7 @@ Dygraph.prototype.doZoom_ = function(lowX, highX) { * @private */ Dygraph.prototype.mouseMove_ = function(event) { - var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(this.hidden_); + var canvasx = Dygraph.pageX(event) - Dygraph.findPosX(this.mouseEventElement_); var points = this.layout_.points; var lastx = -1; @@ -902,9 +919,7 @@ Dygraph.prototype.mouseMove_ = function(event) { // Extract the points we've selected this.selPoints_ = []; - var cumulative_sum = 0; // used only if we have a stackedGraph. var l = points.length; - var isStacked = this.attr_("stackedGraph"); if (!this.attr_("stackedGraph")) { for (var i = 0; i < l; i++) { if (points[i].xval == lastx) { @@ -912,11 +927,11 @@ Dygraph.prototype.mouseMove_ = function(event) { } } } else { - // Stacked points need to be examined in reverse order. + // Need to 'unstack' points starting from the bottom + var cumulative_sum = 0; for (var i = l - 1; i >= 0; i--) { if (points[i].xval == lastx) { - // Clone the point, since we need to 'unstack' it below. - var p = {}; + var p = {}; // Clone the point since we modify it for (var k in points[i]) { p[k] = points[i][k]; } @@ -925,6 +940,7 @@ Dygraph.prototype.mouseMove_ = function(event) { this.selPoints_.push(p); } } + this.selPoints_.reverse(); } if (this.attr_("highlightCallback")) { @@ -1513,17 +1529,19 @@ Dygraph.prototype.drawGraph_ = function(data) { var connectSeparatedPoints = this.attr_('connectSeparatedPoints'); - // For stacked series. - var cumulative_y = []; - var stacked_datasets = []; + // Loop over the fields (series). Go from the last to the first, + // because if they're stacked that's how we accumulate the values. + + var cumulative_y = []; // For stacked series. + var datasets = []; - // Loop over all fields in the dataset - for (var i = 1; i < data[0].length; i++) { + // Loop over all fields and create datasets + for (var i = data[0].length - 1; i >= 1; i--) { if (!this.visibility()[i - 1]) continue; var series = []; for (var j = 0; j < data.length; j++) { - if (data[j][i] || !connectSeparatedPoints) { + if (data[j][i] != null || !connectSeparatedPoints) { var date = data[j][0]; series.push([date, data[j][i]]); } @@ -1569,38 +1587,36 @@ Dygraph.prototype.drawGraph_ = function(data) { if (maxY === null || thisMaxY > maxY) maxY = thisMaxY; if (bars) { - var vals = []; - for (var j=0; j maxY) - maxY = cumulative_y[series[j][0]]; + if (!maxY || cumulative_y[x] > maxY) + maxY = cumulative_y[x]; } - stacked_datasets.push([this.attr_("labels")[i], vals]); - //this.layout_.addDataset(this.attr_("labels")[i], vals); - } else { - this.layout_.addDataset(this.attr_("labels")[i], series); } + + datasets[i] = series; } - if (stacked_datasets.length > 0) { - for (var i = (stacked_datasets.length - 1); i >= 0; i--) { - this.layout_.addDataset(stacked_datasets[i][0], stacked_datasets[i][1]); - } + for (var i = 1; i < datasets.length; i++) { + if (!this.visibility()[i - 1]) continue; + this.layout_.addDataset(this.attr_("labels")[i], datasets[i]); } // Use some heuristics to come up with a good maxY value, unless it's been @@ -2188,6 +2204,7 @@ Dygraph.prototype.updateOptions = function(attrs) { this.valueRange_ = attrs.valueRange; } Dygraph.update(this.user_attrs_, attrs); + Dygraph.update(this.renderOptions_, attrs); this.labelsFromCSV_ = (this.attr_("labels") == null); @@ -2213,6 +2230,11 @@ Dygraph.prototype.updateOptions = function(attrs) { * @param {Number} height Height (in pixels) */ Dygraph.prototype.resize = function(width, height) { + if (this.resize_lock) { + return; + } + this.resize_lock = true; + if ((width === null) != (height === null)) { this.warn("Dygraph.resize() should be called with zero parameters or " + "two non-NULL parameters. Pretending it was zero."); @@ -2235,6 +2257,8 @@ Dygraph.prototype.resize = function(width, height) { this.createInterface_(); this.drawGraph_(this.rawData_); + + this.resize_lock = false; }; /** @@ -2276,6 +2300,39 @@ Dygraph.prototype.setVisibility = function(num, value) { }; /** + * Update the list of annotations and redraw the chart. + */ +Dygraph.prototype.setAnnotations = function(ann) { + this.annotations_ = ann; + this.layout_.setAnnotations(this.annotations_); + this.drawGraph_(this.rawData_); +}; + +/** + * Return the list of annotations. + */ +Dygraph.prototype.annotations = function() { + return this.annotations_; +}; + +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;"; + if (mysheet.insertRule) { // Firefox + mysheet.insertRule(".dygraphDefaultAnnotation { " + rule + " }"); + } else if (mysheet.addRule) { // IE + mysheet.addRule(".dygraphDefaultAnnotation", rule); + } + + Dygraph.addedAnnotationCSS = true; +} + +/** * Create a new canvas element. This is more complex than a simple * document.createElement("canvas") because of IE and excanvas. */