X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=348ef6c57ec96597009b74db60004bff89c01550;hb=88a17b3f3b73348cfe2d986b01751814f7c8724b;hp=bba10284c4772380c2273287c3191b89ef038de9;hpb=8c0599e30c8cfbda74f1f70e8b07e58bc19548ae;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index bba1028..348ef6c 100644 --- a/dygraph.js +++ b/dygraph.js @@ -43,7 +43,10 @@ */ -/*jshint globalstrict: true */ +// For "production" code, this gets set to false by uglifyjs. +if (typeof(DEBUG) === 'undefined') DEBUG=true; + +var Dygraph = (function() { /*global DygraphLayout:false, DygraphCanvasRenderer:false, DygraphOptions:false, G_vmlCanvasManager:false,ActiveXObject:false */ "use strict"; @@ -72,7 +75,7 @@ var Dygraph = function(div, data, opts, opt_fourth_param) { // 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 // to support this usage. - Dygraph.warn("Using deprecated four-argument dygraph constructor"); + console.warn("Using deprecated four-argument dygraph constructor"); this.__old_init__(div, data, opts, opt_fourth_param); } else { this.__init__(div, data, opts); @@ -114,10 +117,8 @@ Dygraph.KMG2_SMALL_LABELS = [ 'm', 'u', 'n', 'p', 'f', 'a', 'z', 'y' ]; * and maxNumberWidth options. * @param {number} x The number to be formatted * @param {Dygraph} opts An options view - * @param {string} name The name of the point's data series - * @param {Dygraph} g The dygraph object */ -Dygraph.numberValueFormatter = function(x, opts, pt, g) { +Dygraph.numberValueFormatter = function(x, opts) { var sigFigs = opts('sigFigs'); if (sigFigs !== null) { @@ -151,7 +152,7 @@ Dygraph.numberValueFormatter = function(x, opts, pt, g) { k_labels = Dygraph.KMB_LABELS; } if (kmg2) { - if (kmb) Dygraph.warn("Setting both labelsKMB and labelsKMG2. Pick one!"); + if (kmb) console.warn("Setting both labelsKMB and labelsKMG2. Pick one!"); k = 1024; k_labels = Dygraph.KMG2_BIG_LABELS; m_labels = Dygraph.KMG2_SMALL_LABELS; @@ -188,8 +189,8 @@ Dygraph.numberValueFormatter = function(x, opts, pt, g) { * variant for use as an axisLabelFormatter. * @private */ -Dygraph.numberAxisLabelFormatter = function(x, granularity, opts, g) { - return Dygraph.numberValueFormatter(x, opts, g); +Dygraph.numberAxisLabelFormatter = function(x, granularity, opts) { + return Dygraph.numberValueFormatter(x, opts); }; /** @@ -331,7 +332,6 @@ Dygraph.DEFAULT_ATTRS = { axisLineWidth: 0.3, gridLineWidth: 0.3, axisLabelColor: "black", - axisLabelFont: "Arial", // TODO(danvk): is this implemented? axisLabelWidth: 50, drawYGrid: true, drawXGrid: true, @@ -345,6 +345,7 @@ Dygraph.DEFAULT_ATTRS = { rangeSelectorHeight: 40, rangeSelectorPlotStrokeColor: "#808FAB", rangeSelectorPlotFillColor: "#A7B1C4", + showInRangeSelector: null, // The ordering here ensures that central lines always appear above any // fill bars/error bars. @@ -444,7 +445,7 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { } if (!div) { - Dygraph.error("Constructing dygraph with a non-existent div!"); + console.error("Constructing dygraph with a non-existent div!"); return; } @@ -532,8 +533,16 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { this.plugins_ = []; var plugins = Dygraph.PLUGINS.concat(this.getOption('plugins')); for (var i = 0; i < plugins.length; i++) { - var Plugin = plugins[i]; - var pluginInstance = new Plugin(); + // the plugins option may contain either plugin classes or instances. + // Plugin instances contain an activate method. + var Plugin = plugins[i]; // either a constructor or an instance. + var pluginInstance; + if (typeof(Plugin.activate) !== 'undefined') { + pluginInstance = Plugin; + } else { + pluginInstance = new Plugin(); + } + var pluginDict = { plugin: pluginInstance, events: {}, @@ -543,6 +552,7 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { var handlers = pluginInstance.activate(this); for (var eventName in handlers) { + if (!handlers.hasOwnProperty(eventName)) continue; // TODO(danvk): validate eventName. pluginDict.events[eventName] = handlers[eventName]; } @@ -574,12 +584,12 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { /** * Triggers a cascade of events to the various plugins which are interested in them. - * Returns true if the "default behavior" should be performed, i.e. if none of - * the event listeners called event.preventDefault(). + * Returns true if the "default behavior" should be prevented, i.e. if one + * of the event listeners called event.preventDefault(). * @private */ Dygraph.prototype.cascadeEvents_ = function(name, extra_props) { - if (!(name in this.eventListeners_)) return true; + if (!(name in this.eventListeners_)) return false; // QUESTION: can we use objects & prototypes to speed this up? var e = { @@ -664,16 +674,16 @@ Dygraph.prototype.toString = function() { * @return { ... } The value of the option. */ Dygraph.prototype.attr_ = function(name, seriesName) { -// - if (typeof(Dygraph.OPTIONS_REFERENCE) === 'undefined') { - Dygraph.error('Must include options reference JS for testing'); - } else if (!Dygraph.OPTIONS_REFERENCE.hasOwnProperty(name)) { - Dygraph.error('Dygraphs is using property ' + name + ', which has no ' + - 'entry in the Dygraphs.OPTIONS_REFERENCE listing.'); - // Only log this error once. - Dygraph.OPTIONS_REFERENCE[name] = true; - } -// + if (DEBUG) { + if (typeof(Dygraph.OPTIONS_REFERENCE) === 'undefined') { + console.error('Must include options reference JS for testing'); + } else if (!Dygraph.OPTIONS_REFERENCE.hasOwnProperty(name)) { + console.error('Dygraphs is using property ' + name + ', which has no ' + + 'entry in the Dygraphs.OPTIONS_REFERENCE listing.'); + // Only log this error once. + Dygraph.OPTIONS_REFERENCE[name] = true; + } + } return seriesName ? this.attributes_.getForSeries(name, seriesName) : this.attributes_.get(name); }; @@ -1067,7 +1077,7 @@ Dygraph.prototype.toPercentXCoord = function(x) { var xRange = this.xAxisRange(); var pct; var logscale = this.attributes_.getForAxis("logscale", 'x') ; - if (logscale == true) { // logscale can be null so we test for true explicitly. + if (logscale === true) { // logscale can be null so we test for true explicitly. var logr0 = Dygraph.log10(xRange[0]); var logr1 = Dygraph.log10(xRange[1]); pct = (Dygraph.log10(x) - logr0) / (logr1 - logr0); @@ -1218,6 +1228,12 @@ Dygraph.prototype.destroy = function() { this.canvas_ctx_.restore(); this.hidden_ctx_.restore(); + // Destroy any plugins, in the reverse order that they were registered. + for (var i = this.plugins_.length - 1; i >= 0; i--) { + var p = this.plugins_.pop(); + if (p.plugin.destroy) p.plugin.destroy(); + } + var removeRecursive = function(node) { while (node.hasChildNodes()) { removeRecursive(node.firstChild); @@ -1232,7 +1248,7 @@ Dygraph.prototype.destroy = function() { Dygraph.removeEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler_); // remove window handlers - Dygraph.removeEvent(window,'resize',this.resizeHandler_); + Dygraph.removeEvent(window,'resize', this.resizeHandler_); this.resizeHandler_ = null; removeRecursive(this.maindiv_); @@ -1471,6 +1487,26 @@ Dygraph.prototype.createDragInterface_ = function() { contextB.dragStartY = Dygraph.dragGetY_(event, contextB); contextB.cancelNextDblclick = false; contextB.tarp.cover(); + }, + destroy: function() { + var context = this; + if (context.isZooming || context.isPanning) { + context.isZooming = false; + context.dragStartX = null; + context.dragStartY = null; + } + + if (context.isPanning) { + context.isPanning = false; + context.draggingDate = null; + context.dateRange = null; + for (var i = 0; i < self.axes_.length; i++) { + delete self.axes_[i].draggingValue; + delete self.axes_[i].dragValueRange; + } + } + + context.tarp.uncover(); } }; @@ -1494,27 +1530,13 @@ Dygraph.prototype.createDragInterface_ = function() { // If the user releases the mouse button during a drag, but not over the // canvas, then it doesn't count as a zooming action. - var mouseUpHandler = function(event) { - if (context.isZooming || context.isPanning) { - context.isZooming = false; - context.dragStartX = null; - context.dragStartY = null; - } - - if (context.isPanning) { - context.isPanning = false; - context.draggingDate = null; - context.dateRange = null; - for (var i = 0; i < self.axes_.length; i++) { - delete self.axes_[i].draggingValue; - delete self.axes_[i].dragValueRange; - } - } - - context.tarp.uncover(); - }; + if (!interactionModel.willDestroyContextMyself) { + var mouseUpHandler = function(event) { + context.destroy(); + }; - this.addAndTrackEvent(document, 'mouseup', mouseUpHandler); + this.addAndTrackEvent(document, 'mouseup', mouseUpHandler); + } }; /** @@ -1579,7 +1601,7 @@ Dygraph.prototype.drawZoomRect_ = function(direction, startX, endX, startY, */ Dygraph.prototype.clearZoomRect_ = function() { this.currentZoomRectArgs_ = null; - this.canvas_ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height); + this.canvas_ctx_.clearRect(0, 0, this.width_, this.height_); }; /** @@ -1620,7 +1642,7 @@ Dygraph.prototype.doZoomXDates_ = function(minDate, maxDate) { var that = this; this.doAnimatedZoom(old_window, new_window, null, null, function() { if (that.getFunctionOption("zoomCallback")) { - that.getFunctionOption("zoomCallback")( + that.getFunctionOption("zoomCallback").call(that, minDate, maxDate, that.yAxisRanges()); } }); @@ -1653,7 +1675,7 @@ Dygraph.prototype.doZoomY_ = function(lowY, highY) { this.doAnimatedZoom(null, null, oldValueRanges, newValueRanges, function() { if (that.getFunctionOption("zoomCallback")) { var xRange = that.xAxisRange(); - that.getFunctionOption("zoomCallback")( + that.getFunctionOption("zoomCallback").call(that, xRange[0], xRange[1], that.yAxisRanges()); } }); @@ -1708,7 +1730,7 @@ Dygraph.prototype.resetZoom = function() { } this.drawGraph_(); if (this.getFunctionOption("zoomCallback")) { - this.getFunctionOption("zoomCallback")( + this.getFunctionOption("zoomCallback").call(this, minDate, maxDate, this.yAxisRanges()); } return; @@ -1751,7 +1773,7 @@ Dygraph.prototype.resetZoom = function() { } } if (that.getFunctionOption("zoomCallback")) { - that.getFunctionOption("zoomCallback")( + that.getFunctionOption("zoomCallback").call(that, minDate, maxDate, that.yAxisRanges()); } }); @@ -1988,7 +2010,7 @@ Dygraph.prototype.mouseMove_ = function(event) { var callback = this.getFunctionOption("highlightCallback"); if (callback && selectionChanged) { - callback(event, + callback.call(this, event, this.lastx_, this.selPoints_, this.lastRow_, @@ -2118,7 +2140,7 @@ Dygraph.prototype.updateSelection_ = function(opt_animFraction) { ctx.lineWidth = this.getNumericOption('strokeWidth', pt.name); ctx.strokeStyle = color; ctx.fillStyle = color; - callback(this, pt.name, ctx, canvasx, pt.canvasy, + callback.call(this, this, pt.name, ctx, canvasx, pt.canvasy, color, circleSize, pt.idx); } ctx.restore(); @@ -2201,10 +2223,10 @@ Dygraph.prototype.setSelection = function(row, opt_seriesName, opt_locked) { */ Dygraph.prototype.mouseOut_ = function(event) { if (this.getFunctionOption("unhighlightCallback")) { - this.getFunctionOption("unhighlightCallback")(event); + this.getFunctionOption("unhighlightCallback").call(this, event); } - if (this.getFunctionOption("hideOverlayOnMouseOut") && !this.lockedSet_) { + if (this.getBooleanOption("hideOverlayOnMouseOut") && !this.lockedSet_) { this.clearSelection(); } }; @@ -2274,6 +2296,7 @@ Dygraph.prototype.isSeriesLocked = function() { */ Dygraph.prototype.loadedEvent_ = function(data) { this.rawData_ = this.parseCSV_(data); + this.cascadeDataDidUpdateEvent_(); this.predraw_(); }; @@ -2345,12 +2368,6 @@ Dygraph.prototype.predraw_ = function() { // TODO(danvk): move more computations out of drawGraph_ and into here. this.computeYAxes_(); - // Create a new plotter. - if (this.plotter_) { - this.cascadeEvents_('clearChart'); - this.plotter_.clear(); - } - if (!this.is_initial_draw_) { this.canvas_ctx_.restore(); this.hidden_ctx_.restore(); @@ -2359,6 +2376,7 @@ Dygraph.prototype.predraw_ = function() { this.canvas_ctx_.save(); this.hidden_ctx_.save(); + // Create a new plotter. this.plotter_ = new DygraphCanvasRenderer(this, this.hidden_, this.hidden_ctx_, @@ -2673,7 +2691,7 @@ Dygraph.prototype.drawGraph_ = function() { if (this.getStringOption("timingName")) { var end = new Date(); - Dygraph.info(this.getStringOption("timingName") + " - drawGraph: " + (end - start) + "ms"); + console.log(this.getStringOption("timingName") + " - drawGraph: " + (end - start) + "ms"); } }; @@ -2690,7 +2708,7 @@ Dygraph.prototype.renderGraph_ = function(is_initial_draw) { if (this.getFunctionOption('underlayCallback')) { // NOTE: we pass the dygraph object to this callback twice to avoid breaking // users who expect a deprecated form of this callback. - this.getFunctionOption('underlayCallback')( + this.getFunctionOption('underlayCallback').call(this, this.hidden_ctx_, this.layout_.getPlotArea(), this, this); } @@ -2705,8 +2723,7 @@ Dygraph.prototype.renderGraph_ = function(is_initial_draw) { // TODO(danvk): is this a performance bottleneck when panning? // The interaction canvas should already be empty in that situation. - this.canvas_.getContext('2d').clearRect(0, 0, this.canvas_.width, - this.canvas_.height); + this.canvas_.getContext('2d').clearRect(0, 0, this.width_, this.height_); if (this.getFunctionOption("drawCallback") !== null) { this.getFunctionOption("drawCallback")(this, is_initial_draw); @@ -3095,7 +3112,7 @@ Dygraph.prototype.parseCSV_ = function(data) { // TODO(danvk): figure out an appropriate way to flag parse errors. vals = inFields[j].split("/"); if (vals.length != 2) { - Dygraph.error('Expected fractional "num/den" values in CSV data ' + + console.error('Expected fractional "num/den" values in CSV data ' + "but found a value '" + inFields[j] + "' on line " + (1 + i) + " ('" + line + "') which is not of this form."); fields[j] = [0, 0]; @@ -3107,7 +3124,7 @@ Dygraph.prototype.parseCSV_ = function(data) { } else if (this.getBooleanOption("errorBars")) { // If there are error bars, values are (value, stddev) pairs if (inFields.length % 2 != 1) { - Dygraph.error('Expected alternating (value, stdev.) pairs in CSV data ' + + console.error('Expected alternating (value, stdev.) pairs in CSV data ' + 'but line ' + (1 + i) + ' has an odd number of values (' + (inFields.length - 1) + "): '" + line + "'"); } @@ -3128,7 +3145,7 @@ Dygraph.prototype.parseCSV_ = function(data) { Dygraph.parseFloat_(vals[1], i, line), Dygraph.parseFloat_(vals[2], i, line) ]; } else { - Dygraph.warn('When using customBars, values must be either blank ' + + console.warn('When using customBars, values must be either blank ' + 'or "low;center;high" tuples (got "' + val + '" on line ' + (1+i)); } @@ -3145,7 +3162,7 @@ Dygraph.prototype.parseCSV_ = function(data) { } if (fields.length != expectedCols) { - Dygraph.error("Number of columns in line " + i + " (" + fields.length + + console.error("Number of columns in line " + i + " (" + fields.length + ") does not agree with number of labels (" + expectedCols + ") " + line); } @@ -3160,7 +3177,7 @@ Dygraph.prototype.parseCSV_ = function(data) { if (fields[j]) all_null = false; } if (all_null) { - Dygraph.warn("The dygraphs 'labels' option is set, but the first row " + + console.warn("The dygraphs 'labels' option is set, but the first row " + "of CSV data ('" + line + "') appears to also contain " + "labels. Will drop the CSV labels and use the option " + "labels."); @@ -3171,7 +3188,7 @@ Dygraph.prototype.parseCSV_ = function(data) { } if (outOfOrder) { - Dygraph.warn("CSV is out of order; order it correctly to speed loading."); + console.warn("CSV is out of order; order it correctly to speed loading."); ret.sort(function(a,b) { return a[0] - b[0]; }); } @@ -3189,17 +3206,17 @@ Dygraph.prototype.parseCSV_ = function(data) { Dygraph.prototype.parseArray_ = function(data) { // Peek at the first x value to see if it's numeric. if (data.length === 0) { - Dygraph.error("Can't plot empty data set"); + console.error("Can't plot empty data set"); return null; } if (data[0].length === 0) { - Dygraph.error("Data set cannot contain an empty row"); + console.error("Data set cannot contain an empty row"); return null; } var i; if (this.attr_("labels") === null) { - Dygraph.warn("Using default labels. Set labels explicitly via 'labels' " + + console.warn("Using default labels. Set labels explicitly via 'labels' " + "in the options parameter"); this.attrs_.labels = [ "X" ]; for (i = 1; i < data[0].length; i++) { @@ -3209,7 +3226,7 @@ Dygraph.prototype.parseArray_ = function(data) { } else { var num_labels = this.attr_("labels"); if (num_labels.length != data[0].length) { - Dygraph.error("Mismatch between number of labels (" + num_labels + ")" + + console.error("Mismatch between number of labels (" + num_labels + ")" + " and number of columns in array (" + data[0].length + ")"); return null; } @@ -3225,13 +3242,13 @@ Dygraph.prototype.parseArray_ = function(data) { var parsedData = Dygraph.clone(data); for (i = 0; i < data.length; i++) { if (parsedData[i].length === 0) { - Dygraph.error("Row " + (1 + i) + " of data is empty"); + console.error("Row " + (1 + i) + " of data is empty"); return null; } if (parsedData[i][0] === null || typeof(parsedData[i][0].getTime) != 'function' || isNaN(parsedData[i][0].getTime())) { - Dygraph.error("x value in row " + (1 + i) + " is not a Date"); + console.error("x value in row " + (1 + i) + " is not a Date"); return null; } parsedData[i][0] = parsedData[i][0].getTime(); @@ -3285,7 +3302,7 @@ Dygraph.prototype.parseDataTable_ = function(data) { this.attrs_.axes.x.ticker = Dygraph.numericTicks; this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter; } else { - Dygraph.error("only 'date', 'datetime' and 'number' types are supported " + + console.error("only 'date', 'datetime' and 'number' types are supported " + "for column 1 of DataTable input (Got '" + indepType + "')"); return null; } @@ -3309,7 +3326,7 @@ Dygraph.prototype.parseDataTable_ = function(data) { } hasAnnotations = true; } else { - Dygraph.error("Only 'number' is supported as a dependent type with Gviz." + + console.error("Only 'number' is supported as a dependent type with Gviz." + " 'string' is only supported if displayAnnotations is true"); } } @@ -3331,7 +3348,7 @@ Dygraph.prototype.parseDataTable_ = function(data) { var row = []; if (typeof(data.getValue(i, 0)) === 'undefined' || data.getValue(i, 0) === null) { - Dygraph.warn("Ignoring row " + i + + console.warn("Ignoring row " + i + " of DataTable because of undefined or null first column."); continue; } @@ -3377,7 +3394,7 @@ Dygraph.prototype.parseDataTable_ = function(data) { } if (outOfOrder) { - Dygraph.warn("DataTable is out of order; order it correctly to speed loading."); + console.warn("DataTable is out of order; order it correctly to speed loading."); ret.sort(function(a,b) { return a[0] - b[0]; }); } this.rawData_ = ret; @@ -3389,6 +3406,17 @@ Dygraph.prototype.parseDataTable_ = function(data) { }; /** + * Signals to plugins that the chart data has updated. + * This happens after the data has updated but before the chart has redrawn. + */ +Dygraph.prototype.cascadeDataDidUpdateEvent_ = function() { + // TODO(danvk): there are some issues checking xAxisRange() and using + // toDomCoords from handlers of this event. The visible range should be set + // when the chart is drawn, not derived from the data. + this.cascadeEvents_('dataDidUpdate', {}); +}; + +/** * Get the CSV data. If it's in a function, call that function. If it's in a * file, do an XMLHttpRequest to get it. * @private @@ -3403,11 +3431,13 @@ Dygraph.prototype.start_ = function() { if (Dygraph.isArrayLike(data)) { this.rawData_ = this.parseArray_(data); + this.cascadeDataDidUpdateEvent_(); this.predraw_(); } else if (typeof data == 'object' && typeof data.getColumnRange == 'function') { // must be a DataTable from gviz. this.parseDataTable_(data); + this.cascadeDataDidUpdateEvent_(); this.predraw_(); } else if (typeof data == 'string') { // Heuristic: a newline means it's CSV data. Otherwise it's an URL. @@ -3439,7 +3469,7 @@ Dygraph.prototype.start_ = function() { req.send(null); } } else { - Dygraph.error("Unknown data format: " + (typeof data)); + console.error("Unknown data format: " + (typeof data)); } }; @@ -3497,6 +3527,10 @@ Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { this.attributes_.reparseSeries(); if (file) { + // This event indicates that the data is about to change, but hasn't yet. + // TODO(danvk): support cancelation of the update via this event. + this.cascadeEvents_('dataWillUpdate', {}); + this.file_ = file; if (!block_redraw) this.start_(); } else { @@ -3519,6 +3553,7 @@ Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { Dygraph.mapLegacyOptions_ = function(attrs) { var my_attrs = {}; for (var k in attrs) { + if (!attrs.hasOwnProperty(k)) continue; if (k == 'file') continue; if (attrs.hasOwnProperty(k)) my_attrs[k] = attrs[k]; } @@ -3530,7 +3565,7 @@ Dygraph.mapLegacyOptions_ = function(attrs) { }; var map = function(opt, axis, new_opt) { if (typeof(attrs[opt]) != 'undefined') { - Dygraph.warn("Option " + opt + " is deprecated. Use the " + + console.warn("Option " + opt + " is deprecated. Use the " + new_opt + " option for the " + axis + " axis instead. " + "(e.g. { axes : { " + axis + " : { " + new_opt + " : ... } } } " + "(see http://dygraphs.com/per-axis.html for more information."); @@ -3573,7 +3608,7 @@ Dygraph.prototype.resize = function(width, height) { this.resize_lock = true; if ((width === null) != (height === null)) { - Dygraph.warn("Dygraph.resize() should be called with zero parameters or " + + console.warn("Dygraph.resize() should be called with zero parameters or " + "two non-NULL parameters. Pretending it was zero."); width = height = null; } @@ -3636,7 +3671,7 @@ Dygraph.prototype.visibility = function() { Dygraph.prototype.setVisibility = function(num, value) { var x = this.visibility(); if (num < 0 || num >= x.length) { - Dygraph.warn("invalid series number in setVisibility: " + num); + console.warn("invalid series number in setVisibility: " + num); } else { x[num] = value; this.predraw_(); @@ -3664,7 +3699,7 @@ Dygraph.prototype.setAnnotations = function(ann, suppressDraw) { Dygraph.addAnnotationRule(); this.annotations_ = ann; if (!this.layout_) { - Dygraph.warn("Tried to setAnnotations before dygraph was ready. " + + console.warn("Tried to setAnnotations before dygraph was ready. " + "Try setting them in a ready() block. See " + "dygraphs.com/tests/annotation.html"); return; @@ -3718,7 +3753,7 @@ Dygraph.prototype.ready = function(callback) { if (this.is_initial_draw_) { this.readyFns_.push(callback); } else { - callback(this); + callback.call(this, this); } }; @@ -3761,5 +3796,9 @@ Dygraph.addAnnotationRule = function() { } } - Dygraph.warn("Unable to add default annotation CSS rule; display may be off."); + console.warn("Unable to add default annotation CSS rule; display may be off."); }; + +return Dygraph; + +})();