X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=97da32acb755782994e3aec17eb83744dbd58688;hb=e9a32469f3fb0fa4438993d5c46e046b07488bec;hp=cec7c20a2e00e7b6c965194aca6bf12aa2722946;hpb=2de7166c125ecb7bbfe6a0c815887ee6e4a475b6;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index cec7c20..97da32a 100644 --- a/dygraph.js +++ b/dygraph.js @@ -91,7 +91,8 @@ Dygraph.DEFAULT_ROLL_PERIOD = 1; Dygraph.DEFAULT_WIDTH = 480; Dygraph.DEFAULT_HEIGHT = 320; -Dygraph.ANIMATION_STEPS = 10; +// For max 60 Hz. animation: +Dygraph.ANIMATION_STEPS = 12; Dygraph.ANIMATION_DURATION = 200; // These are defined before DEFAULT_ATTRS so that it can refer to them. @@ -355,6 +356,10 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { attrs = Dygraph.mapLegacyOptions_(attrs); + if (typeof(div) == 'string') { + div = document.getElementById(div); + } + if (!div) { Dygraph.error("Constructing dygraph with a non-existent div!"); return; @@ -408,6 +413,15 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { // TODO(nikhilk): Add any other stackedGraph checks here. } + // These two options have a bad interaction. See issue 359. + if (attrs.showRangeSelector && attrs.animatedZooms) { + this.warn('You should not set animatedZooms=true when using the range selector.'); + attrs.animatedZooms = false; + } + + // DEPRECATION WARNING: All option processing should be moved from + // attrs_ and user_attrs_ to options_, which holds all this information. + // // Dygraphs has many options, some of which interact with one another. // To keep track of everything, we maintain two sets of options: // @@ -431,14 +445,16 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { this.registeredEvents_ = []; this.eventListeners_ = {}; + this.attributes_ = new DygraphOptions(this); + // Create the containing DIV and other interactive elements this.createInterface_(); // Activate plugins. this.plugins_ = []; for (var i = 0; i < Dygraph.PLUGINS.length; i++) { - var plugin = Dygraph.PLUGINS[i]; - var pluginInstance = new plugin(); + var Plugin = Dygraph.PLUGINS[i]; + var pluginInstance = new Plugin(); var pluginDict = { plugin: pluginInstance, events: {}, @@ -482,7 +498,7 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { * @private */ Dygraph.prototype.cascadeEvents_ = function(name, extra_props) { - if (!name in this.eventListeners_) return true; + if (!(name in this.eventListeners_)) return true; // QUESTION: can we use objects & prototypes to speed this up? var e = { @@ -518,11 +534,13 @@ Dygraph.prototype.cascadeEvents_ = function(name, extra_props) { * Axis is an optional parameter. Can be set to 'x' or 'y'. * * The zoomed status for an axis is set whenever a user zooms using the mouse - * or when the dateWindow or valueRange are updated (unless the isZoomedIgnoreProgrammaticZoom - * option is also specified). + * or when the dateWindow or valueRange are updated (unless the + * isZoomedIgnoreProgrammaticZoom option is also specified). */ Dygraph.prototype.isZoomed = function(axis) { - if (axis == null) return this.zoomed_x_ || this.zoomed_y_; + if (axis === null || axis === undefined) { + return this.zoomed_x_ || this.zoomed_y_; + } if (axis === 'x') return this.zoomed_x_; if (axis === 'y') return this.zoomed_y_; throw "axis parameter is [" + axis + "] must be null, 'x' or 'y'."; @@ -560,30 +578,7 @@ Dygraph.prototype.attr_ = function(name, seriesName) { } // - var sources = []; - sources.push(this.attrs_); - if (this.user_attrs_) { - sources.push(this.user_attrs_); - if (seriesName) { - if (this.user_attrs_.hasOwnProperty(seriesName)) { - sources.push(this.user_attrs_[seriesName]); - } - if (seriesName === this.highlightSet_ && - this.user_attrs_.hasOwnProperty('highlightSeriesOpts')) { - sources.push(this.user_attrs_['highlightSeriesOpts']); - } - } - } - - var ret = null; - for (var i = sources.length - 1; i >= 0; --i) { - var source = sources[i]; - if (source.hasOwnProperty(name)) { - ret = source[name]; - break; - } - } - return ret; + return seriesName ? this.attributes_.getForSeries(name, seriesName) : this.attributes_.get(name); }; /** @@ -1245,6 +1240,10 @@ Dygraph.prototype.createDragInterface_ = function() { boundedDates: null, // [minDate, maxDate] boundedValues: null, // [[minValue, maxValue] ...] + // We cover iframes during mouse interactions. See comments in + // dygraph-utils.js for more info on why this is a good idea. + tarp: new Dygraph.IFrameTarp(), + // contextB is the same thing as this context object but renamed. initializeMouseDown: function(event, g, contextB) { // prevents mouse drags from selecting page text. @@ -1260,6 +1259,7 @@ Dygraph.prototype.createDragInterface_ = function() { contextB.dragStartX = g.dragGetX_(event, contextB); contextB.dragStartY = g.dragGetY_(event, contextB); contextB.cancelNextDblclick = false; + contextB.tarp.cover(); } }; @@ -1299,6 +1299,8 @@ Dygraph.prototype.createDragInterface_ = function() { delete self.axes_[i].dragValueRange; } } + + context.tarp.uncover(); }; this.addEvent(document, 'mouseup', this.mouseUpHandler_); @@ -1521,7 +1523,9 @@ Dygraph.prototype.doUnzoom_ = function() { newValueRanges = []; for (i = 0; i < this.axes_.length; i++) { var axis = this.axes_[i]; - newValueRanges.push(axis.valueRange != null ? axis.valueRange : axis.extremeRange); + newValueRanges.push((axis.valueRange !== null && + axis.valueRange !== undefined) ? + axis.valueRange : axis.extremeRange); } } @@ -1653,7 +1657,7 @@ Dygraph.prototype.findClosestPoint = function(domX, domY) { var minDist = Infinity; var idx = -1; var dist, dx, dy, point, closestPoint, closestSeries; - for (var setIdx = 0; setIdx < this.layout_.datasets.length; ++setIdx) { + for ( var setIdx = this.layout_.datasets.length - 1 ; setIdx >= 0 ; --setIdx ) { var points = this.layout_.points[setIdx]; for (var i = 0; i < points.length; ++i) { var point = points[i]; @@ -1723,7 +1727,7 @@ Dygraph.prototype.findStackedPoint = function(domX, domY) { } } // Stop if the point (domX, py) is above this series' upper edge - if (setIdx == 0 || py < domY) { + if (setIdx === 0 || py < domY) { closestPoint = p1; closestSeries = setIdx; } @@ -1754,7 +1758,7 @@ Dygraph.prototype.mouseMove_ = function(event) { var highlightSeriesOpts = this.attr_("highlightSeriesOpts"); var selectionChanged = false; - if (highlightSeriesOpts && !this.lockedSet_) { + if (highlightSeriesOpts && !this.isSeriesLocked()) { var closest; if (this.attr_("stackedGraph")) { closest = this.findStackedPoint(canvasx, canvasy); @@ -1952,7 +1956,7 @@ Dygraph.prototype.setSelection = function(row, opt_seriesName, opt_locked) { point = this.layout_.unstackPointAtIndex(setIdx, row); } - if (!(point.yval === null)) this.selPoints_.push(point); + if (point.yval !== null) this.selPoints_.push(point); } } } else { @@ -2047,6 +2051,14 @@ Dygraph.prototype.getHighlightSeries = function() { }; /** + * Returns true if the currently-highlighted series was locked + * via setSelection(..., seriesName, true). + */ +Dygraph.prototype.isSeriesLocked = function() { + return this.lockedSet_; +}; + +/** * Fires when there's data available to be graphed. * @param {String} data Raw CSV data to be plotted * @private @@ -2096,7 +2108,7 @@ Dygraph.prototype.extremeValues_ = function(series) { // With custom bars, maxY is the max of the high values. for (j = 0; j < series.length; j++) { y = series[j][1][0]; - if (!y) continue; + if (y === null || isNaN(y)) continue; var low = y - series[j][1][1]; var high = y + series[j][1][2]; if (low > y) low = y; // this can happen with custom bars, @@ -2162,7 +2174,8 @@ Dygraph.prototype.predraw_ = function() { // rolling averages. this.rolledSeries_ = [null]; // x-axis is the first series and it's special for (var i = 1; i < this.numColumns(); i++) { - var logScale = this.attr_('logscale', i); // TODO(klausw): this looks wrong + // var logScale = this.attr_('logscale', i); // TODO(klausw): this looks wrong // konigsberg thinks so too. + var logScale = this.attr_('logscale'); var series = this.extractSeries_(this.rawData_, i, logScale); series = this.rollingAverage(series, this.rollPeriod_); this.rolledSeries_.push(series); @@ -2500,7 +2513,6 @@ Dygraph.prototype.computeYAxes_ = function() { } } - // New axes options for (axis = 0; axis < this.axes_.length; axis++) { if (axis === 0) { opts = this.optionsViewForAxis_('y' + (axis ? '2' : '')); @@ -2920,7 +2932,8 @@ Dygraph.prototype.parseFloat_ = function(x, opt_line_no, opt_line) { */ Dygraph.prototype.parseCSV_ = function(data) { var ret = []; - var lines = data.split("\n"); + var line_delimiter = Dygraph.detectLineDelimiter(data); + var lines = data.split(line_delimiter || "\n"); var vals, j; // Use the default delimiter or fall back to a tab if that makes sense. @@ -2934,6 +2947,7 @@ Dygraph.prototype.parseCSV_ = function(data) { // User hasn't explicitly set labels, so they're (presumably) in the CSV. start = 1; this.attrs_.labels = lines[0].split(delim); // NOTE: _not_ user_attrs_. + this.attributes_.reparseSeries(); } var line_no = 0; @@ -3070,8 +3084,9 @@ Dygraph.prototype.parseArray_ = function(data) { "in the options parameter"); this.attrs_.labels = [ "X" ]; for (i = 1; i < data[0].length; i++) { - this.attrs_.labels.push("Y" + i); + this.attrs_.labels.push("Y" + i); // Not user_attrs_. } + this.attributes_.reparseSeries(); } else { var num_labels = this.attr_("labels"); if (num_labels.length != data[0].length) { @@ -3081,7 +3096,7 @@ Dygraph.prototype.parseArray_ = function(data) { } } - if (Dygraph.isDateLike(data[0][0])) { + if (Dygraph.isDateLike(data[0][0]) { // Some intelligent defaults for a date x-axis. this.attrs_.axes.x.valueFormatter = Dygraph.dateString_; this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter; @@ -3134,7 +3149,7 @@ Dygraph.prototype.parseDataTable_ = function(data) { num = Math.floor((num - 1) / 26); } return shortText; - } + }; var cols = data.getNumberOfColumns(); var rows = data.getNumberOfRows(); @@ -3276,7 +3291,8 @@ Dygraph.prototype.start_ = function() { this.predraw_(); } else if (typeof data == 'string') { // Heuristic: a newline means it's CSV data. Otherwise it's an URL. - if (data.indexOf('\n') >= 0) { + var line_delimiter = Dygraph.detectLineDelimiter(data); + if (line_delimiter) { this.loadedEvent_(data); } else { var req = new XMLHttpRequest(); @@ -3382,6 +3398,10 @@ Dygraph.mapLegacyOptions_ = function(attrs) { }; var map = function(opt, axis, new_opt) { if (typeof(attrs[opt]) != 'undefined') { + Dygraph.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]; }