X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=f82285b73f56fd65f93d25e490545ab6be8b4b71;hb=0755e27d80c9d4c7dffbeaded74b545d71c11466;hp=cf13a590ba41213cb365819cb825e872b02093ca;hpb=e0269a3d8b5b65fecc93226ffbb2f429a8951997;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index cf13a59..f82285b 100644 --- a/dygraph.js +++ b/dygraph.js @@ -83,7 +83,7 @@ var Dygraph = function(div, data, opts, opt_fourth_param) { }; Dygraph.NAME = "Dygraph"; -Dygraph.VERSION = "1.0.1"; +Dygraph.VERSION = "1.1.0"; Dygraph.__repr__ = function() { return "[" + Dygraph.NAME + " " + Dygraph.VERSION + "]"; }; @@ -190,7 +190,7 @@ Dygraph.numberValueFormatter = function(x, opts) { * @private */ Dygraph.numberAxisLabelFormatter = function(x, granularity, opts) { - return Dygraph.numberValueFormatter(x, opts); + return Dygraph.numberValueFormatter.call(this, x, opts); }; /** @@ -226,12 +226,12 @@ Dygraph.dateAxisLabelFormatter = function(date, granularity, opts) { if (granularity >= Dygraph.DECADAL) { return '' + year; } else if (granularity >= Dygraph.MONTHLY) { - return Dygraph.SHORT_MONTH_NAMES_[month] + ' ' + year; + return Dygraph.SHORT_MONTH_NAMES_[month] + ' ' + year; } else { var frac = hours * 3600 + mins * 60 + secs + 1e-3 * millis; if (frac === 0 || granularity >= Dygraph.DAILY) { // e.g. '21 Jan' (%d%b) - return Dygraph.zeropad(day) + ' ' + Dygraph.SHORT_MONTH_NAMES_[month]; + return Dygraph.zeropad(day) + ' ' + Dygraph.SHORT_MONTH_NAMES_[month]; } else { return Dygraph.hmsString_(hours, mins, secs); } @@ -310,9 +310,7 @@ Dygraph.DEFAULT_ATTRS = { stackedGraphNaNFill: 'all', hideOverlayOnMouseOut: true, - // TODO(danvk): support 'onmouseover' and 'never', and remove synonyms. - legend: 'onmouseover', // the only relevant value at the moment is 'always'. - + legend: 'onmouseover', stepPlot: false, avoidMinZero: false, xRangePad: 0, @@ -324,15 +322,11 @@ Dygraph.DEFAULT_ATTRS = { xLabelHeight: 18, yLabelWidth: 18, - drawXAxis: true, - drawYAxis: true, axisLineColor: "black", axisLineWidth: 0.3, gridLineWidth: 0.3, axisLabelColor: "black", axisLabelWidth: 50, - drawYGrid: true, - drawXGrid: true, gridLineColor: "rgb(128,128,128)", interactionModel: null, // will be set to Dygraph.Interaction.defaultModel @@ -425,21 +419,10 @@ Dygraph.prototype.__old_init__ = function(div, file, labels, attrs) { * @private */ Dygraph.prototype.__init__ = function(div, file, attrs) { - // Hack for IE: if we're using excanvas and the document hasn't finished - // loading yet (and hence may not have initialized whatever it needs to - // initialize), then keep calling this routine periodically until it has. - if (/MSIE/.test(navigator.userAgent) && !window.opera && - typeof(G_vmlCanvasManager) != 'undefined' && - document.readyState != 'complete') { - var self = this; - setTimeout(function() { self.__init__(div, file, attrs); }, 100); - return; - } - // Support two-argument constructor if (attrs === null || attrs === undefined) { attrs = {}; } - attrs = Dygraph.mapLegacyOptions_(attrs); + attrs = Dygraph.copyUserAttrs_(attrs); if (typeof(div) == 'string') { div = document.getElementById(div); @@ -450,8 +433,6 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { return; } - this.isUsingExcanvas_ = typeof(G_vmlCanvasManager) != 'undefined'; - // Copy the important bits into the object // TODO(danvk): most of these should just stay in the attrs_ dictionary. this.maindiv_ = div; @@ -1296,18 +1277,7 @@ Dygraph.prototype.createPlotKitCanvas_ = function(canvas) { * @private */ Dygraph.prototype.createMouseEventElement_ = function() { - if (this.isUsingExcanvas_) { - var elem = document.createElement("div"); - elem.style.position = 'absolute'; - elem.style.backgroundColor = 'white'; - elem.style.filter = 'alpha(opacity=0)'; - elem.style.width = this.width_ + "px"; - elem.style.height = this.height_ + "px"; - this.graphDiv.appendChild(elem); - return elem; - } else { - return this.canvas_; - } + return this.canvas_; }; /** @@ -1590,10 +1560,6 @@ Dygraph.prototype.drawZoomRect_ = function(direction, startX, endX, startY, this.layout_.getPlotArea().w, Math.abs(endY - startY)); } } - - if (this.isUsingExcanvas_) { - this.currentZoomRectArgs_ = [direction, startX, endX, startY, endY, 0, 0, 0]; - } }; /** @@ -2053,6 +2019,14 @@ Dygraph.prototype.animateSelection_ = function(direction) { var thisId = ++this.animateId; var that = this; + var cleanupIfClearing = function() { + // if we haven't reached fadeLevel 0 in the max frame time, + // ensure that the clear happens and just go to 0 + if (that.fadeLevel !== 0 && direction < 0) { + that.fadeLevel = 0; + that.clearSelection(); + } + }; Dygraph.repeatAndCleanup( function(n) { // ignore simultaneous animations @@ -2065,7 +2039,7 @@ Dygraph.prototype.animateSelection_ = function(direction) { that.updateSelection_(that.fadeLevel / totalSteps); } }, - steps, millis, function() {}); + steps, millis, cleanupIfClearing); }; /** @@ -2076,6 +2050,7 @@ Dygraph.prototype.animateSelection_ = function(direction) { Dygraph.prototype.updateSelection_ = function(opt_animFraction) { /*var defaultPrevented = */ this.cascadeEvents_('select', { + selectedRow: this.lastRow_, selectedX: this.lastx_, selectedPoints: this.selPoints_ }); @@ -2120,10 +2095,6 @@ Dygraph.prototype.updateSelection_ = function(opt_animFraction) { 2 * maxCircleSize + 2, this.height_); } - if (this.isUsingExcanvas_ && this.currentZoomRectArgs_) { - Dygraph.prototype.drawZoomRect_.apply(this, this.currentZoomRectArgs_); - } - if (this.selPoints_.length > 0) { // Draw colored circles over the center of each selected point var canvasx = this.selPoints_[0].canvasx; @@ -2155,7 +2126,7 @@ Dygraph.prototype.updateSelection_ = function(opt_animFraction) { * legend. The selection can be cleared using clearSelection() and queried * using getSelection(). * @param {number} row Row number that should be highlighted (i.e. appear with - * hover dots on the chart). Set to false to clear any selection. + * hover dots on the chart). * @param {seriesName} optional series name to highlight that series with the * the highlightSeriesOpts setting. * @param { locked } optional If true, keep seriesName selected when mousing @@ -2318,7 +2289,7 @@ Dygraph.prototype.addXTicks_ = function() { var xTicks = xAxisOptionsView('ticker')( range[0], range[1], - this.width_, // TODO(danvk): should be area.width + this.plotter_.area.w, // TODO(danvk): should be area.width xAxisOptionsView, this); // var msg = 'ticker(' + range[0] + ', ' + range[1] + ', ' + this.width_ + ', ' + this.attr_('pixelsPerXLabel') + ') -> ' + JSON.stringify(xTicks); @@ -2972,7 +2943,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { var ticker = opts('ticker'); axis.ticks = ticker(axis.computedValueRange[0], axis.computedValueRange[1], - this.height_, // TODO(danvk): should be area.height + this.plotter_.area.h, opts, this); // Define the first independent axis as primary axis. @@ -3003,7 +2974,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { axis.ticks = ticker(axis.computedValueRange[0], axis.computedValueRange[1], - this.height_, // TODO(danvk): should be area.height + this.plotter_.area.h, opts, this, tick_values); @@ -3495,9 +3466,9 @@ Dygraph.prototype.start_ = function() { Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { if (typeof(block_redraw) == 'undefined') block_redraw = false; - // mapLegacyOptions_ drops the "file" parameter as a convenience to us. + // copyUserAttrs_ drops the "file" parameter as a convenience to us. var file = input_attrs.file; - var attrs = Dygraph.mapLegacyOptions_(input_attrs); + var attrs = Dygraph.copyUserAttrs_(input_attrs); // TODO(danvk): this is a mess. Move these options into attr_. if ('rollPeriod' in attrs) { @@ -3546,50 +3517,15 @@ Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { }; /** - * Returns a copy of the options with deprecated names converted into current - * names. Also drops the (potentially-large) 'file' attribute. If the caller is - * interested in that, they should save a copy before calling this. - * @private + * Make a copy of input attributes, removing file as a convenience. */ -Dygraph.mapLegacyOptions_ = function(attrs) { +Dygraph.copyUserAttrs_ = 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]; } - - var set = function(axis, opt, value) { - if (!my_attrs.axes) my_attrs.axes = {}; - if (!my_attrs.axes[axis]) my_attrs.axes[axis] = {}; - my_attrs.axes[axis][opt] = value; - }; - var map = function(opt, axis, new_opt) { - if (typeof(attrs[opt]) != 'undefined') { - 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."); - set(axis, new_opt, attrs[opt]); - delete my_attrs[opt]; - } - }; - - // This maps, e.g., xValueFormater -> axes: { x: { valueFormatter: ... } } - map('xValueFormatter', 'x', 'valueFormatter'); - map('pixelsPerXLabel', 'x', 'pixelsPerLabel'); - map('xAxisLabelFormatter', 'x', 'axisLabelFormatter'); - map('xTicker', 'x', 'ticker'); - map('yValueFormatter', 'y', 'valueFormatter'); - map('pixelsPerYLabel', 'y', 'pixelsPerLabel'); - map('yAxisLabelFormatter', 'y', 'axisLabelFormatter'); - map('yTicker', 'y', 'ticker'); - map('drawXGrid', 'x', 'drawGrid'); - map('drawXAxis', 'x', 'drawAxis'); - map('drawYGrid', 'y', 'drawGrid'); - map('drawYAxis', 'y', 'drawAxis'); - map('xAxisLabelWidth', 'x', 'axisLabelWidth'); - map('yAxisLabelWidth', 'y', 'axisLabelWidth'); return my_attrs; }; @@ -3666,19 +3602,25 @@ Dygraph.prototype.visibility = function() { }; /** - * Changes the visiblity of a series. + * Changes the visibility of one or more series. * - * @param {number} num the series index + * @param {number|number[]} num the series index or an array of series indices * @param {boolean} value true or false, identifying the visibility. */ Dygraph.prototype.setVisibility = function(num, value) { var x = this.visibility(); - if (num < 0 || num >= x.length) { - console.warn("invalid series number in setVisibility: " + num); - } else { - x[num] = value; - this.predraw_(); + + if (num.constructor !== Array) num = [num]; + + for (var i = 0; i < num.length; i++) { + if (num[i] < 0 || num[i] >= x.length) { + console.warn("invalid series number in setVisibility: " + num[i]); + } else { + x[num[i]] = value; + } } + + this.predraw_(); }; /** @@ -3741,6 +3683,35 @@ Dygraph.prototype.indexFromSetName = function(name) { }; /** + * Find the row number corresponding to the given x-value. + * Returns null if there is no such x-value in the data. + * If there are multiple rows with the same x-value, this will return the + * first one. + * @param {number} xVal The x-value to look for (e.g. millis since epoch). + * @return {?number} The row number, which you can pass to getValue(), or null. + */ +Dygraph.prototype.getRowForX = function(xVal) { + var low = 0, + high = this.numRows() - 1; + + while (low <= high) { + var idx = (high + low) >> 1; + var x = this.getValue(idx, 0); + if (x < xVal) { + low = idx + 1; + } else if (x > xVal) { + high = idx - 1; + } else if (low != idx) { // equal, but there may be an earlier match. + high = idx; + } else { + return idx; + } + } + + return null; +}; + +/** * 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