*/
/*jshint globalstrict: true */
-/*global DygraphLayout:false, DygraphCanvasRenderer:false, DygraphOptions:false, G_vmlCanvasManager:false */
+/*global DygraphLayout:false, DygraphCanvasRenderer:false, DygraphOptions:false, G_vmlCanvasManager:false,ActiveXObject:false */
"use strict";
/**
* options, see http://dygraphs.com/options.html.
*/
var Dygraph = function(div, data, opts, opt_fourth_param) {
+ // These have to go above the "Hack for IE" in __init__ since .ready() can be
+ // called as soon as the constructor returns. Once support for OldIE is
+ // dropped, this can go down with the rest of the initializers.
+ this.is_initial_draw_ = true;
+ this.readyFns_ = [];
+
if (opt_fourth_param !== undefined) {
// Old versions of dygraphs took in the series labels as a constructor
// parameter. This doesn't make sense anymore, but it's easy to continue
};
Dygraph.NAME = "Dygraph";
-Dygraph.VERSION = "1.2";
+Dygraph.VERSION = "1.0.0";
Dygraph.__repr__ = function() {
return "[" + this.NAME + " " + this.VERSION + "]";
};
this.fractions_ = attrs.fractions || false;
this.dateWindow_ = attrs.dateWindow || null;
- this.is_initial_draw_ = true;
this.annotations_ = [];
// Zoomed indicators - These indicate when the graph has been zoomed and on what axis.
if (prevDirection == Dygraph.HORIZONTAL) {
ctx.clearRect(Math.min(startX, prevEndX), this.layout_.getPlotArea().y,
Math.abs(startX - prevEndX), this.layout_.getPlotArea().h);
- } else if (prevDirection == Dygraph.VERTICAL){
+ } else if (prevDirection == Dygraph.VERTICAL) {
ctx.clearRect(this.layout_.getPlotArea().x, Math.min(startY, prevEndY),
this.layout_.getPlotArea().w, Math.abs(startY - prevEndY));
}
*/
Dygraph.prototype.findClosestRow = function(domX) {
var minDistX = Infinity;
- var pointIdx = -1, setIdx = -1;
+ var closestRow = -1;
var sets = this.layout_.points;
for (var i = 0; i < sets.length; i++) {
var points = sets[i];
var dist = Math.abs(point.canvasx - domX);
if (dist < minDistX) {
minDistX = dist;
- setIdx = i;
- pointIdx = j;
+ closestRow = point.idx;
}
}
}
- // TODO(danvk): remove this function; it's trivial and has only one use.
- return this.idxToRow_(setIdx, pointIdx);
+ return closestRow;
};
/**
* @private
*/
Dygraph.prototype.getLeftBoundary_ = function(setIdx) {
- if(!isNaN(setIdx) && setIdx < this.boundaryIds_.length){
- return this.boundaryIds_[setIdx][0];
+ if (this.boundaryIds_[setIdx]) {
+ return this.boundaryIds_[setIdx][0];
} else {
for (var i = 0; i < this.boundaryIds_.length; i++) {
if (this.boundaryIds_[i] !== undefined) {
}
};
-/**
- * Transforms layout_.points index into data row number.
- * @param int layout_.points index
- * @return int row number, or -1 if none could be found.
- * @private
- */
-Dygraph.prototype.idxToRow_ = function(setIdx, rowIdx) {
- if (rowIdx < 0) return -1;
-
- var boundary = this.getLeftBoundary_(setIdx);
- return boundary + rowIdx;
-};
-
Dygraph.prototype.animateSelection_ = function(direction) {
var totalSteps = 10;
var millis = 30;
this.plotter_.clear();
}
- if(!this.is_initial_draw_) {
+ if (!this.is_initial_draw_) {
this.canvas_ctx_.restore();
this.hidden_ctx_.restore();
}
/**
* Converts a series to a Point array.
*
+ * @private
* @param {Array.<Array.<(?number|Array<?number>)>} series Array where
* series[row] = [x,y] or [x, [y, err]] or [x, [y, yplus, yminus]].
* @param {boolean} bars True if error bars or custom bars are being drawn.
* to reflect the stacked values.
* @param {string} fillMethod Interpolation method, one of 'all', 'inside', or
* 'none'.
+ * @private
*/
Dygraph.stackPoints_ = function(
points, cumulativeYval, seriesExtremes, fillMethod) {
if (this.attr_("drawCallback") !== null) {
this.attr_("drawCallback")(this, is_initial_draw);
}
+ if (is_initial_draw) {
+ this.readyFired_ = true;
+ while (this.readyFns_.length > 0) {
+ var fn = this.readyFns_.pop();
+ fn(this);
+ }
+ }
};
/**
}
- if(independentTicks) {
+ if (independentTicks) {
axis.independentTicks = independentTicks;
var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
var ticker = opts('ticker');
} else {
// Calculate the rolling average for the first rollPeriod - 1 points where
// there is not enough data to roll over the full number of points
- if (!this.attr_("errorBars")){
+ if (!this.attr_("errorBars")) {
if (rollPeriod == 1) {
return originalData;
}
if (line_delimiter) {
this.loadedEvent_(data);
} else {
- var req = new XMLHttpRequest();
+ // REMOVE_FOR_IE
+ var req;
+ if (window.XMLHttpRequest) {
+ // Firefox, Opera, IE7, and other browsers will use the native object
+ req = new XMLHttpRequest();
+ } else {
+ // IE 5 and 6 will use the ActiveX control
+ req = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+
var caller = this;
req.onreadystatechange = function () {
if (req.readyState == 4) {
this.annotations_ = ann;
if (!this.layout_) {
this.warn("Tried to setAnnotations before dygraph was ready. " +
- "Try setting them in a drawCallback. See " +
+ "Try setting them in a ready() block. See " +
"dygraphs.com/tests/annotation.html");
return;
}
};
/**
- * Get the internal dataset index given its name. These are numbered starting from 0,
- * and only count visible sets.
- * @private
+ * Trigger a callback when the dygraph has drawn itself and is ready to be
+ * manipulated. This is primarily useful when dygraphs has to do an XHR for the
+ * data (i.e. a URL is passed as the data source) and the chart is drawn
+ * asynchronously. If the chart has already drawn, the callback will fire
+ * immediately.
+ *
+ * This is a good place to call setAnnotation().
+ *
+ * @param {function(!Dygraph)} callback The callback to trigger when the chart
+ * is ready.
*/
-Dygraph.prototype.datasetIndexFromSetName_ = function(name) {
- return this.datasetIndex_[this.indexFromSetName(name)];
+Dygraph.prototype.ready = function(callback) {
+ if (this.is_initial_draw_) {
+ this.readyFns_.push(callback);
+ } else {
+ callback(this);
+ }
};
/**