X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=6adb43bdc413cde408e47d90b2d376d848581261;hb=eee806a0323c685c0ba9f9e40d80f050ac587d64;hp=888abd91569682a4c5bf8fdccf7f4eac117bf0b6;hpb=da1369a5acf5304973dcc061c6682fd167ee67da;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index 888abd9..6adb43b 100644 --- a/dygraph.js +++ b/dygraph.js @@ -304,9 +304,6 @@ Dygraph.prototype.__init__ = function(div, file, attrs) { this.boundaryIds_ = []; - // Make a note of whether labels will be pulled from the CSV file. - this.labelsFromCSV_ = (this.attr_("labels") == null); - // Create the containing DIV and other interactive elements this.createInterface_(); @@ -451,9 +448,11 @@ Dygraph.prototype.xAxisExtremes = function() { */ Dygraph.prototype.yAxisRange = function(idx) { if (typeof(idx) == "undefined") idx = 0; - if (idx < 0 || idx >= this.axes_.length) return null; - return [ this.axes_[idx].computedValueRange[0], - this.axes_[idx].computedValueRange[1] ]; + if (idx < 0 || idx >= this.axes_.length) { + return null; + } + var axis = this.axes_[idx]; + return [ axis.computedValueRange[0], axis.computedValueRange[1] ]; }; /** @@ -1230,7 +1229,7 @@ Dygraph.Interaction.movePan = function(event, g, context) { } } - g.drawGraph_(); + g.drawGraph_(false); }; /** @@ -1247,7 +1246,19 @@ Dygraph.Interaction.movePan = function(event, g, context) { * dragStartX/dragStartY/etc. properties). This function modifies the context. */ Dygraph.Interaction.endPan = function(event, g, context) { + context.dragEndX = g.dragGetX_(event, context); + context.dragEndY = g.dragGetY_(event, context); + + var regionWidth = Math.abs(context.dragEndX - context.dragStartX); + var regionHeight = Math.abs(context.dragEndY - context.dragStartY); + + if (regionWidth < 2 && regionHeight < 2 && + g.lastx_ != undefined && g.lastx_ != -1) { + Dygraph.Interaction.treatMouseOpAsClick(g, event, context); + } + // TODO(konigsberg): Clear the context data from the axis. + // (replace with "context = {}" ?) // TODO(konigsberg): mouseup should just delete the // context object, and mousedown should create a new one. context.isPanning = false; @@ -1314,6 +1325,33 @@ Dygraph.Interaction.moveZoom = function(event, g, context) { context.prevDragDirection = context.dragDirection; }; +Dygraph.Interaction.treatMouseOpAsClick = function(g, event, context) { + // TODO(danvk): pass along more info about the points, e.g. 'x' + if (g.attr_('clickCallback') != null) { + g.attr_('clickCallback')(event, g.lastx_, g.selPoints_, context); + } + if (g.attr_('pointClickCallback')) { + // check if the click was on a particular point. + var closestIdx = -1; + var closestDistance = 0; + for (var i = 0; i < g.selPoints_.length; i++) { + var p = g.selPoints_[i]; + var distance = Math.pow(p.canvasx - context.dragEndX, 2) + + Math.pow(p.canvasy - context.dragEndY, 2); + if (closestIdx == -1 || distance < closestDistance) { + closestDistance = distance; + closestIdx = i; + } + } + + // Allow any click within two pixels of the dot. + var radius = g.attr_('highlightCircleSize') + 2; + if (closestDistance <= 5 * 5) { + g.attr_('pointClickCallback')(event, g.selPoints_[closestIdx]); + } + } +} + /** * Called in response to an interaction model operation that * responds to an event that performs a zoom based on previously defined @@ -1329,7 +1367,6 @@ Dygraph.Interaction.moveZoom = function(event, g, context) { * dragStartX/dragStartY/etc. properties). This function modifies the context. */ Dygraph.Interaction.endZoom = function(event, g, context) { - // TODO(konigsberg): Refactor or rename this fn -- it deals with clicks, too. context.isZooming = false; context.dragEndX = g.dragGetX_(event, context); context.dragEndY = g.dragGetY_(event, context); @@ -1338,30 +1375,7 @@ Dygraph.Interaction.endZoom = function(event, g, context) { if (regionWidth < 2 && regionHeight < 2 && g.lastx_ != undefined && g.lastx_ != -1) { - // TODO(danvk): pass along more info about the points, e.g. 'x' - if (g.attr_('clickCallback') != null) { - g.attr_('clickCallback')(event, g.lastx_, g.selPoints_); - } - if (g.attr_('pointClickCallback')) { - // check if the click was on a particular point. - var closestIdx = -1; - var closestDistance = 0; - for (var i = 0; i < g.selPoints_.length; i++) { - var p = g.selPoints_[i]; - var distance = Math.pow(p.canvasx - context.dragEndX, 2) + - Math.pow(p.canvasy - context.dragEndY, 2); - if (closestIdx == -1 || distance < closestDistance) { - closestDistance = distance; - closestIdx = i; - } - } - - // Allow any click within two pixels of the dot. - var radius = g.attr_('highlightCircleSize') + 2; - if (closestDistance <= 5 * 5) { - g.attr_('pointClickCallback')(event, g.selPoints_[closestIdx]); - } - } + Dygraph.Interaction.treatMouseOpAsClick(g, event, context); } if (regionWidth >= 10 && context.dragDirection == Dygraph.HORIZONTAL) { @@ -2664,9 +2678,19 @@ Dygraph.prototype.predraw_ = function() { * Update the graph with new data. This method is called when the viewing area * has changed. If the underlying data or options have changed, predraw_ will * be called before drawGraph_ is called. + * + * clearSelection, when undefined or true, causes this.clearSelection to be + * called at the end of the draw operation. This should rarely be defined, + * and never true (that is it should be undefined most of the time, and + * rarely false.) + * * @private */ -Dygraph.prototype.drawGraph_ = function() { +Dygraph.prototype.drawGraph_ = function(clearSelection) { + if (typeof(clearSelection) === 'undefined') { + clearSelection = true; + } + var data = this.rawData_; // This is used to set the second parameter to drawCallback, below. @@ -2809,13 +2833,15 @@ Dygraph.prototype.drawGraph_ = function() { // Generate a static legend before any particular point is selected. this.setLegendHTML_(); } else { - if (typeof(this.selPoints_) !== 'undefined' && this.selPoints_.length) { - // We should select the point nearest the page x/y here, but it's easier - // to just clear the selection. This prevents erroneous hover dots from - // being displayed. - this.clearSelection(); - } else { - this.clearSelection(); + if (clearSelection) { + if (typeof(this.selPoints_) !== 'undefined' && this.selPoints_.length) { + // We should select the point nearest the page x/y here, but it's easier + // to just clear the selection. This prevents erroneous hover dots from + // being displayed. + this.clearSelection(); + } else { + this.clearSelection(); + } } } @@ -2836,6 +2862,17 @@ Dygraph.prototype.drawGraph_ = function() { * indices are into the axes_ array. */ Dygraph.prototype.computeYAxes_ = function() { + // Preserve valueWindow settings if they exist, and if the user hasn't + // specified a new valueRange. + var valueWindows; + if (this.axes_ != undefined && this.user_attrs_.hasOwnProperty("valueRange") == false) { + valueWindows = []; + for (var index = 0; index < this.axes_.length; index++) { + valueWindows.push(this.axes_[index].valueWindow); + } + } + + this.axes_ = [{ yAxisId : 0, g : this }]; // always have at least one y-axis. this.seriesToAxisMap_ = {}; @@ -2912,6 +2949,13 @@ Dygraph.prototype.computeYAxes_ = function() { if (vis[i - 1]) seriesToAxisFiltered[s] = this.seriesToAxisMap_[s]; } this.seriesToAxisMap_ = seriesToAxisFiltered; + + if (valueWindows != undefined) { + // Restore valueWindow settings. + for (var index = 0; index < valueWindows.length; index++) { + this.axes_[index].valueWindow = valueWindows[index]; + } + } }; /** @@ -3320,9 +3364,10 @@ Dygraph.prototype.parseCSV_ = function(data) { } var start = 0; - if (this.labelsFromCSV_) { + if (!('labels' in this.user_attrs_)) { + // User hasn't explicitly set labels, so they're (presumably) in the CSV. start = 1; - this.attrs_.labels = lines[0].split(delim); + this.attrs_.labels = lines[0].split(delim); // NOTE: _not_ user_attrs_. } var line_no = 0; @@ -3633,6 +3678,8 @@ Dygraph.dateStrToMillis = function(str) { // These functions are all based on MochiKit. /** + * Copies all the properties from o to self. + * * @private */ Dygraph.update = function (self, o) { @@ -3738,10 +3785,20 @@ Dygraph.prototype.start_ = function() { *
  • errorBars: changes whether the data contains stddev
  • * * + * There's a huge variety of options that can be passed to this method. For a + * full list, see http://dygraphs.com/options.html. + * * @param {Object} attrs The new properties and values + * @param {Boolean} [block_redraw] Usually the chart is redrawn after every + * call to updateOptions(). If you know better, you can pass true to explicitly + * block the redraw. This can be useful for chaining updateOptions() calls, + * avoiding the occasional infinite loop and preventing redraws when it's not + * necessary (e.g. when updating a callback). */ -Dygraph.prototype.updateOptions = function(attrs) { - // TODO(danvk): this is a mess. Rethink this function. +Dygraph.prototype.updateOptions = function(attrs, block_redraw) { + if (typeof(block_redraw) == 'undefined') block_redraw = false; + + // TODO(danvk): this is a mess. Move these options into attr_. if ('rollPeriod' in attrs) { this.rollPeriod_ = attrs.rollPeriod; } @@ -3764,13 +3821,11 @@ Dygraph.prototype.updateOptions = function(attrs) { Dygraph.update(this.user_attrs_, attrs); - this.labelsFromCSV_ = (this.attr_("labels") == null); - if (attrs['file']) { this.file_ = attrs['file']; - this.start_(); + if (!block_redraw) this.start_(); } else { - this.predraw_(); + if (!block_redraw) this.predraw_(); } };