From 50522d1b2b07c6034be6304b8efc5dd3d154e2db Mon Sep 17 00:00:00 2001 From: simonkwesi <0x35@tylinar.de> Date: Thu, 21 Jan 2016 21:18:41 +0100 Subject: [PATCH 01/54] Extended list of users --- docs/users.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/users.html b/docs/users.html index 0f362c5a4..663036229 100644 --- a/docs/users.html +++ b/docs/users.html @@ -111,6 +111,17 @@

Known Users

+
  • + Ghanastocks.net
    + + Ghanastocks.net is a financial platform offering information on the stocks traded on the Ghana Stock Exchange. + Dygraphs is used to display the stock charts. On the front page a tiny preview graph with no interaction model and + labels is used, the quote pages uses a standard version of dygraphs and the detailed chart is displayed using two + dygraphs instances, one for the volume bars and one for the chart, which are synchronized through a custom highlight + callback. + +
  • +

    Are you using dygraphs? Please let Dan know and he'll add your link here!

    From 0d9ed3ab9f7fe2ea4102fca7d752656d80a9973a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Seren?= Date: Mon, 8 Feb 2016 13:04:32 +0100 Subject: [PATCH 02/54] Bugfix: Import missing dygraph-utils.js The IFrameTarp.prototype.cover function calls `findPos` from the `dygraph-utils.js` file but does not import it. This fixes #724 --- src/iframe-tarp.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/iframe-tarp.js b/src/iframe-tarp.js index b6c3de1af..42100c668 100644 --- a/src/iframe-tarp.js +++ b/src/iframe-tarp.js @@ -23,6 +23,8 @@ * * @constructor */ +import * as utils from './dygraph-utils'; + function IFrameTarp() { /** @type {Array.} */ this.tarps = []; From 6813609a3d4529f2f2a89a10c7f910aca6d59ab4 Mon Sep 17 00:00:00 2001 From: Petr Shevtsov Date: Fri, 26 Feb 2016 07:31:06 +0500 Subject: [PATCH 03/54] Update gallery.css Fix #458 --- gallery/gallery.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gallery/gallery.css b/gallery/gallery.css index df899dfb4..2febc685f 100644 --- a/gallery/gallery.css +++ b/gallery/gallery.css @@ -122,7 +122,7 @@ a { position: absolute; left: 200px; right: 10px; - top: 100px; + top: 150px; bottom: 10px; } From f1d5ee3e25241c0cbc194d5f300f2b025f92f777 Mon Sep 17 00:00:00 2001 From: Klaus Weidner Date: Tue, 1 Mar 2016 13:57:05 -0800 Subject: [PATCH 04/54] Fix yRangePad for logscale graphs, add tests. Also includes a minor refactor to consolidate duplicated code for toDataCoord calculations on logscale axes. Fixes issue #661. --- auto_tests/tests/axis_labels.js | 27 ++++++++ auto_tests/tests/range_tests.js | 2 +- auto_tests/tests/to_dom_coords.js | 14 ++++ src/dygraph-utils.js | 33 +++++++++ src/dygraph.js | 111 +++++++++--------------------- 5 files changed, 108 insertions(+), 79 deletions(-) diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index 0af808522..c390392f2 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -687,6 +687,33 @@ it('testLogScale', function() { assert.deepEqual(['0','200','400','600','800','1000'], Util.getYLabels()); }); +/** + * Verify that log scale axis range works with yRangePad. + * + * This is a regression test for https://github.com/danvk/dygraphs/issues/661 . + */ +it('testLogScalePad', function() { + var g = new Dygraph("graph", + [[0, 1e-5], [1, 0.25], [2, 1], [3, 3], [4, 10]], { + width: 250, + height: 130, + logscale: true, + yRangePad: 30, + axes: {y: {valueRange: [1, 10]}}, + labels: ['X', 'Y'] + }); + var nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; }); + assert.deepEqual(['1', '7', '30'], nonEmptyLabels); + + g.updateOptions({ yRangePad: 10, axes: {y: {valueRange: [0.25005, 3]}} }); + nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; }); + assert.deepEqual(['0.4', '1', '3'], nonEmptyLabels); + + g.updateOptions({ axes: {y: {valueRange: [0.01, 3]}} }); + nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; }); + assert.deepEqual(['0.01','0.1','0.7','5'], nonEmptyLabels); +}); + /** * Verify that include zero range is properly specified. */ diff --git a/auto_tests/tests/range_tests.js b/auto_tests/tests/range_tests.js index ff1018e15..19d429478 100644 --- a/auto_tests/tests/range_tests.js +++ b/auto_tests/tests/range_tests.js @@ -342,7 +342,7 @@ it('testLogscalePad', function() { yRangePad: 30 }, [[-10, 10], [10, 10], [30, 1000]], - [-10, 30], [5.01691, 1993.25801]); + [-10, 30], [5.623, 1778.279]); }); /** diff --git a/auto_tests/tests/to_dom_coords.js b/auto_tests/tests/to_dom_coords.js index 454050115..e5bda3b19 100644 --- a/auto_tests/tests/to_dom_coords.js +++ b/auto_tests/tests/to_dom_coords.js @@ -225,6 +225,20 @@ it('testChartLogarithmic_YAxis', function() { assert.deepEqual([400, 0], g.toDomCoords(10, 4)); assert.deepEqual([400, 400], g.toDomCoords(10, 1)); assert.deepEqual([400, 200], g.toDomCoords(10, 2)); + + // Verify that the margins are adjusted appropriately for yRangePad. + g.updateOptions({yRangePad: 40}); + assertDeepCloseTo([0, 4], g.toDataCoords(0, 40), epsilon); + assertDeepCloseTo([0, 1], g.toDataCoords(0, 360), epsilon); + assertDeepCloseTo([10, 4], g.toDataCoords(400, 40), epsilon); + assertDeepCloseTo([10, 1], g.toDataCoords(400, 360), epsilon); + assertDeepCloseTo([10, 2], g.toDataCoords(400, 200), epsilon); + + assertDeepCloseTo([0, 40], g.toDomCoords(0, 4), epsilon); + assertDeepCloseTo([0, 360], g.toDomCoords(0, 1), epsilon); + assertDeepCloseTo([400, 40], g.toDomCoords(10, 4), epsilon); + assertDeepCloseTo([400, 360], g.toDomCoords(10, 1), epsilon); + assertDeepCloseTo([400, 200], g.toDomCoords(10, 2), epsilon); }); it('testChartLogarithmic_XAxis', function() { diff --git a/src/dygraph-utils.js b/src/dygraph-utils.js index c2ed9bb75..3a3e637b8 100644 --- a/src/dygraph-utils.js +++ b/src/dygraph-utils.js @@ -28,6 +28,39 @@ export var log10 = function(x) { return Math.log(x) / LN_TEN; }; +/** + * @private + * @param {number} r0 + * @param {number} r1 + * @param {number} pct + * @return {number} + */ +export var logRangeFraction = function(r0, r1, pct) { + // Computing the inverse of toPercentXCoord. The function was arrived at with + // the following steps: + // + // Original calcuation: + // pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0]))); + // + // Multiply both sides by the right-side demoninator. + // pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0]) + // + // add log(xRange[0]) to both sides + // log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])) = log(x); + // + // Swap both sides of the equation, + // log(x) = log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])) + // + // Use both sides as the exponent in 10^exp and we're done. + // x = 10 ^ (log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0]))) + + var logr0 = log10(r0); + var logr1 = log10(r1); + var exponent = logr0 + (pct * (logr1 - logr0)); + var value = Math.pow(LOG_SCALE, exponent); + return value; +}; + /** A dotted line stroke pattern. */ export var DOTTED_LINE = [2, 2]; /** A dashed line stroke pattern. */ diff --git a/src/dygraph.js b/src/dygraph.js index 41e5cc15a..e5053ba15 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -632,32 +632,8 @@ Dygraph.prototype.toDataXCoord = function(x) { if (!this.attributes_.getForAxis("logscale", 'x')) { return xRange[0] + (x - area.x) / area.w * (xRange[1] - xRange[0]); } else { - // TODO: remove duplicate code? - // Computing the inverse of toDomCoord. var pct = (x - area.x) / area.w; - - // Computing the inverse of toPercentXCoord. The function was arrived at with - // the following steps: - // - // Original calcuation: - // pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0]))); - // - // Multiply both sides by the right-side demoninator. - // pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0]) - // - // add log(xRange[0]) to both sides - // log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])) = log(x); - // - // Swap both sides of the equation, - // log(x) = log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])) - // - // Use both sides as the exponent in 10^exp and we're done. - // x = 10 ^ (log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0]))) - var logr0 = utils.log10(xRange[0]); - var logr1 = utils.log10(xRange[1]); - var exponent = logr0 + (pct * (logr1 - logr0)); - var value = Math.pow(utils.LOG_SCALE, exponent); - return value; + return utils.logRangeFraction(xRange[0], xRange[1], pct); } }; @@ -681,32 +657,8 @@ Dygraph.prototype.toDataYCoord = function(y, axis) { } else { // Computing the inverse of toDomCoord. var pct = (y - area.y) / area.h; - - // Computing the inverse of toPercentYCoord. The function was arrived at with - // the following steps: - // - // Original calcuation: - // pct = (log(yRange[1]) - log(y)) / (log(yRange[1]) - log(yRange[0])); - // - // Multiply both sides by the right-side demoninator. - // pct * (log(yRange[1]) - log(yRange[0])) = log(yRange[1]) - log(y); - // - // subtract log(yRange[1]) from both sides. - // (pct * (log(yRange[1]) - log(yRange[0]))) - log(yRange[1]) = -log(y); - // - // and multiply both sides by -1. - // log(yRange[1]) - (pct * (logr1 - log(yRange[0])) = log(y); - // - // Swap both sides of the equation, - // log(y) = log(yRange[1]) - (pct * (log(yRange[1]) - log(yRange[0]))); - // - // Use both sides as the exponent in 10^exp and we're done. - // y = 10 ^ (log(yRange[1]) - (pct * (log(yRange[1]) - log(yRange[0])))); - var logr0 = utils.log10(yRange[0]); - var logr1 = utils.log10(yRange[1]); - var exponent = logr1 - (pct * (logr1 - logr0)); - var value = Math.pow(utils.LOG_SCALE, exponent); - return value; + // Note reversed yRange, y1 is on top with pct==0. + return utils.logRangeFraction(yRange[1], yRange[0], pct); } }; @@ -2602,25 +2554,21 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { } } - var maxAxisY, minAxisY; - if (logscale) { - if (ypadCompat) { + var maxAxisY = maxY, minAxisY = minY; + if (ypadCompat) { + if (logscale) { maxAxisY = maxY + ypad * span; minAxisY = minY; } else { - var logpad = Math.exp(Math.log(span) * ypad); - maxAxisY = maxY * logpad; - minAxisY = minY / logpad; - } - } else { - maxAxisY = maxY + ypad * span; - minAxisY = minY - ypad * span; - - // Backwards-compatible behavior: Move the span to start or end at zero if it's - // close to zero, but not if avoidMinZero is set. - if (ypadCompat && !this.getBooleanOption("avoidMinZero")) { - if (minAxisY < 0 && minY >= 0) minAxisY = 0; - if (maxAxisY > 0 && maxY <= 0) maxAxisY = 0; + maxAxisY = maxY + ypad * span; + minAxisY = minY - ypad * span; + + // Backwards-compatible behavior: Move the span to start or end at zero if it's + // close to zero, but not if avoidMinZero is set. + if (!this.getBooleanOption("avoidMinZero")) { + if (minAxisY < 0 && minY >= 0) minAxisY = 0; + if (maxAxisY > 0 && maxY <= 0) maxAxisY = 0; + } } } axis.extremeRange = [minAxisY, maxAxisY]; @@ -2634,21 +2582,28 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) { // This is a user-set value range for this axis. var y0 = isNullUndefinedOrNaN(axis.valueRange[0]) ? axis.extremeRange[0] : axis.valueRange[0]; var y1 = isNullUndefinedOrNaN(axis.valueRange[1]) ? axis.extremeRange[1] : axis.valueRange[1]; - if (!ypadCompat) { - if (axis.logscale) { - var logpad = Math.exp(Math.log(span) * ypad); - y0 *= logpad; - y1 /= logpad; - } else { - span = y1 - y0; - y0 -= span * ypad; - y1 += span * ypad; - } - } axis.computedValueRange = [y0, y1]; } else { axis.computedValueRange = axis.extremeRange; } + if (!axis.valueWindow && !ypadCompat) { + // When using yRangePad, adjust the upper/lower bounds to add + // padding unless the user has zoomed/panned the Y axis range. + if (logscale) { + y0 = axis.computedValueRange[0]; + y1 = axis.computedValueRange[1]; + var y0pct = ypad / (2 * ypad - 1); + var y1pct = (ypad - 1) / (2 * ypad - 1); + axis.computedValueRange[0] = utils.logRangeFraction(y0, y1, y0pct); + axis.computedValueRange[1] = utils.logRangeFraction(y0, y1, y1pct); + } else { + y0 = axis.computedValueRange[0]; + y1 = axis.computedValueRange[1]; + span = y1 - y0; + axis.computedValueRange[0] = y0 - span * ypad; + axis.computedValueRange[1] = y1 + span * ypad; + } + } if (independentTicks) { From 93ec1094eb75477b455efaa7adeb10190b87992b Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 16 Mar 2016 12:43:48 -0400 Subject: [PATCH 05/54] Add new issue and PR templates --- CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 20 ++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 14 ++++++++++++++ 3 files changed, 34 insertions(+) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..75d0c7a6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,20 @@ +Filing a bug report? Please include the following: + +1. Link to a page which demonstrates the problem, preferably a jsfiddle (use http://dygraphs.com/fiddle as a template) +2. Browser and Operating System that exhibit the problem +3. Version of dygraphs that you're using + +It also helps if you include the non-compacted version of the JS on your +page. For instance, instead of doing this: + +```html + +``` + +do this: + +```html + +``` + +This makes error messages and debugging simpler. The jsfiddle does this automatically. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..474eeed5b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +Please read the guide to making dygraphs changes: +http://dygraphs.com/changes.html + +Pull Requests will only be accepted if: + +- You clearly explain what you're adding and why you believe it's an + improvement. For example: "Fixes issue #123". +- You adhere to the style of the rest of the dygraphs code base. +- You write an `auto_test` for the code that you're adding. + +Be sure to document any new options you add. Also be aware that PRs which add +options are likely to be rejected. dygraphs already has many options. If you +can fit your feature into one of those or implement it as a plugin, it will be +more likely to get merged. From 902091b8b33555845682681f64048f7ed1811c27 Mon Sep 17 00:00:00 2001 From: Marcus Lewis Date: Wed, 4 May 2016 20:03:36 -0700 Subject: [PATCH 06/54] Bugfix: Unwanted drawn point when prevCanvasX is 0 --- src/dygraph-canvas.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dygraph-canvas.js b/src/dygraph-canvas.js index 7ba66ffc8..bd37e67e0 100644 --- a/src/dygraph-canvas.js +++ b/src/dygraph-canvas.js @@ -220,18 +220,18 @@ DygraphCanvasRenderer._drawSeries = function(e, prevCanvasX = prevCanvasY = null; } else { isIsolated = false; - if (drawGapPoints || !prevCanvasX) { + if (drawGapPoints || prevCanvasX === null) { iter.nextIdx_ = i; iter.next(); nextCanvasY = iter.hasNext ? iter.peek.canvasy : null; var isNextCanvasYNullOrNaN = nextCanvasY === null || nextCanvasY != nextCanvasY; - isIsolated = (!prevCanvasX && isNextCanvasYNullOrNaN); + isIsolated = (prevCanvasX === null && isNextCanvasYNullOrNaN); if (drawGapPoints) { // Also consider a point to be "isolated" if it's adjacent to a // null point, excluding the graph edges. - if ((!first && !prevCanvasX) || + if ((!first && prevCanvasX === null) || (iter.hasNext && isNextCanvasYNullOrNaN)) { isIsolated = true; } From 401ff9f17c622f3173cc8d34cfcf3e444620d7d0 Mon Sep 17 00:00:00 2001 From: Marcus Lewis Date: Thu, 5 May 2016 12:55:17 -0700 Subject: [PATCH 07/54] Add unit test to detect the "unwanted draw point" --- auto_tests/tests/draw_gap_edge_points.js | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 auto_tests/tests/draw_gap_edge_points.js diff --git a/auto_tests/tests/draw_gap_edge_points.js b/auto_tests/tests/draw_gap_edge_points.js new file mode 100644 index 000000000..3d92b0f32 --- /dev/null +++ b/auto_tests/tests/draw_gap_edge_points.js @@ -0,0 +1,47 @@ +/** + * @fileoverview Test cases for the option "drawGapEdgePoints" + */ + +import Dygraph from '../../src/dygraph'; +import * as utils from '../../src/dygraph-utils'; + +describe("draw-gap-edge-points", function() { + + cleanupAfterEach(); + + it("shouldn't draw any points by default", function() { + var called = false; + var g = new Dygraph(document.getElementById("graph"), + [[0, 0], + [1, 1], + [2, 2], + [3, 3], + [4, 4], + [5, 5]], + {labels: ['a', 'b'], + drawGapEdgePoints: true, + drawPointCallback: function() { called = true; }}); + + assert.isFalse(called); + }); + + it("shouldn't draw any points by default (no axes)", function() { + var called = false; + var g = new Dygraph(document.getElementById("graph"), + [[0, 0], + [1, 1], + [2, 2], + [3, 3], + [4, 4], + [5, 5]], + {labels: ['a', 'b'], + drawGapEdgePoints: true, + drawPointCallback: function() { called = true; }, + axes: { + x: { drawAxis: false }, + y: { drawAxis: false } + }}); + + assert.isFalse(called); + }); +}); From b55a71d768d2f8de62877c32b3aec9e9975ac389 Mon Sep 17 00:00:00 2001 From: Justin Standring Date: Fri, 8 Jul 2016 16:05:40 -0700 Subject: [PATCH 08/54] Check for new options before updating synchronised graphs (Fixes #760) --- src/extras/synchronizer.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) mode change 100644 => 100755 src/extras/synchronizer.js diff --git a/src/extras/synchronizer.js b/src/extras/synchronizer.js old mode 100644 new mode 100755 index bf5b6f34b..6f369f3a0 --- a/src/extras/synchronizer.js +++ b/src/extras/synchronizer.js @@ -153,6 +153,16 @@ var synchronize = function(/* dygraphs..., opts */) { }; }; +function arraysAreEqual(a, b) { + if (!Array.isArray(a) || !Array.isArray(b)) return false; + var i = a.length; + if (i !== b.length) return false; + while (i--) { + if (a[i] !== b[i]) return false; + } + return true; +} + function attachZoomHandlers(gs, syncOpts, prevCallbacks) { var block = false; for (var i = 0; i < gs.length; i++) { @@ -173,6 +183,13 @@ function attachZoomHandlers(gs, syncOpts, prevCallbacks) { } continue; } + + // Only redraw if there are new options + if (arraysAreEqual(opts.dateWindow, gs[j].getOption('dateWindow')) && + arraysAreEqual(opts.valueRange, gs[j].getOption('valueRange'))) { + continue; + } + gs[j].updateOptions(opts); } block = false; From bd6ee5dcf9017abcbefa480e79756a6957c5c7ed Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Tue, 2 Aug 2016 15:00:32 -0400 Subject: [PATCH 09/54] Implement tick.label_v. --- src/dygraph-layout.js | 14 +++++++++----- src/plugins/axes.js | 25 ++++++++++++------------- src/plugins/grid.js | 14 ++++++++------ 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/dygraph-layout.js b/src/dygraph-layout.js index 3bc91354e..c32a9e5c4 100644 --- a/src/dygraph-layout.js +++ b/src/dygraph-layout.js @@ -276,14 +276,16 @@ DygraphLayout.prototype._evaluateLineCharts = function() { }; DygraphLayout.prototype._evaluateLineTicks = function() { - var i, tick, label, pos; + var i, tick, label, pos, v, has_tick; this.xticks = []; for (i = 0; i < this.xTicks_.length; i++) { tick = this.xTicks_[i]; label = tick.label; - pos = this.dygraph_.toPercentXCoord(tick.v); + has_tick = !('label_v' in tick); + v = has_tick ? tick.v : tick.label_v; + pos = this.dygraph_.toPercentXCoord(v); if ((pos >= 0.0) && (pos < 1.0)) { - this.xticks.push([pos, label]); + this.xticks.push({pos, label, has_tick}); } } @@ -293,9 +295,11 @@ DygraphLayout.prototype._evaluateLineTicks = function() { for (var j = 0; j < axis.ticks.length; j++) { tick = axis.ticks[j]; label = tick.label; - pos = this.dygraph_.toPercentYCoord(tick.v, i); + has_tick = !('label_v' in tick); + v = has_tick ? tick.v : tick.label_v; + pos = this.dygraph_.toPercentYCoord(v, i); if ((pos > 0.0) && (pos <= 1.0)) { - this.yticks.push([i, pos, label]); + this.yticks.push({axis: i, pos, label, has_tick}); } } } diff --git a/src/plugins/axes.js b/src/plugins/axes.js index e9135344b..f93f36fce 100644 --- a/src/plugins/axes.js +++ b/src/plugins/axes.js @@ -99,7 +99,7 @@ axes.prototype.willDrawChart = function(e) { !g.getOptionForAxis('drawAxis', 'y2')) { return; } - + // Round pixels to half-integer boundaries for crisper drawing. function halfUp(x) { return Math.round(x) + 0.5; } function halfDown(y){ return Math.round(y) - 0.5; } @@ -170,21 +170,20 @@ axes.prototype.willDrawChart = function(e) { if (layout.yticks && layout.yticks.length > 0) { var num_axes = g.numAxes(); var getOptions = [makeOptionGetter('y'), makeOptionGetter('y2')]; - for (i = 0; i < layout.yticks.length; i++) { - tick = layout.yticks[i]; - if (typeof(tick) == 'function') return; // <-- when would this happen? + for (var tick of layout.yticks) { + if (tick.label === undefined) continue; // this tick only has a grid line. x = area.x; var sgn = 1; var prec_axis = 'y1'; var getAxisOption = getOptions[0]; - if (tick[0] == 1) { // right-side y-axis + if (tick.axis == 1) { // right-side y-axis x = area.x + area.w; sgn = -1; prec_axis = 'y2'; getAxisOption = getOptions[1]; } var fontSize = getAxisOption('axisLabelFontSize'); - y = area.y + tick[1] * area.h; + y = area.y + tick.pos * area.h; /* Tick marks are currently clipped, so don't bother drawing them. context.beginPath(); @@ -194,7 +193,7 @@ axes.prototype.willDrawChart = function(e) { context.stroke(); */ - label = makeDiv(tick[2], 'y', num_axes == 2 ? prec_axis : null); + label = makeDiv(tick.label, 'y', num_axes == 2 ? prec_axis : null); var top = (y - fontSize / 2); if (top < 0) top = 0; @@ -203,10 +202,10 @@ axes.prototype.willDrawChart = function(e) { } else { label.style.top = top + 'px'; } - if (tick[0] === 0) { + if (tick.axis === 0) { label.style.left = (area.x - getAxisOption('axisLabelWidth') - getAxisOption('axisTickSize')) + 'px'; label.style.textAlign = 'right'; - } else if (tick[0] == 1) { + } else if (tick.axis == 1) { label.style.left = (area.x + area.w + getAxisOption('axisTickSize')) + 'px'; label.style.textAlign = 'left'; @@ -263,9 +262,9 @@ axes.prototype.willDrawChart = function(e) { if (g.getOptionForAxis('drawAxis', 'x')) { if (layout.xticks) { var getAxisOption = makeOptionGetter('x'); - for (i = 0; i < layout.xticks.length; i++) { - tick = layout.xticks[i]; - x = area.x + tick[0] * area.w; + for (var tick of layout.xticks) { + if (tick.label === undefined) continue; // this tick only has a grid line. + x = area.x + tick.pos * area.w; y = area.y + area.h; /* Tick marks are currently clipped, so don't bother drawing them. @@ -276,7 +275,7 @@ axes.prototype.willDrawChart = function(e) { context.stroke(); */ - label = makeDiv(tick[1], 'x'); + label = makeDiv(tick.label, 'x'); label.style.textAlign = 'center'; label.style.top = (y + getAxisOption('axisTickSize')) + 'px'; diff --git a/src/plugins/grid.js b/src/plugins/grid.js index 16a83a2b8..25126db3c 100644 --- a/src/plugins/grid.js +++ b/src/plugins/grid.js @@ -62,9 +62,10 @@ grid.prototype.willDrawChart = function(e) { ticks = layout.yticks; ctx.save(); // draw grids for the different y axes - for (i = 0; i < ticks.length; i++) { - var axis = ticks[i][0]; - if(drawGrid[axis]) { + for (var tick of ticks) { + if (!tick.has_tick) continue; + var axis = tick.axis; + if (drawGrid[axis]) { ctx.save(); if (stroking[axis]) { if (ctx.setLineDash) ctx.setLineDash(strokePattern[axis]); @@ -73,7 +74,7 @@ grid.prototype.willDrawChart = function(e) { ctx.lineWidth = lineWidths[axis]; x = halfUp(area.x); - y = halfDown(area.y + ticks[i][1] * area.h); + y = halfDown(area.y + tick.pos * area.h); ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + area.w, y); @@ -96,8 +97,9 @@ grid.prototype.willDrawChart = function(e) { } ctx.strokeStyle = g.getOptionForAxis('gridLineColor', 'x'); ctx.lineWidth = g.getOptionForAxis('gridLineWidth', 'x'); - for (i = 0; i < ticks.length; i++) { - x = halfUp(area.x + ticks[i][0] * area.w); + for (var tick of ticks) { + if (!tick.has_tick) continue; + x = halfUp(area.x + tick.pos * area.w); y = halfDown(area.y + area.h); ctx.beginPath(); ctx.moveTo(x, y); From ad739e06ecde73b8a05ff619fa901474b408ddaa Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Tue, 2 Aug 2016 15:15:51 -0400 Subject: [PATCH 10/54] Demo of label_v --- tests/label_v.html | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/label_v.html diff --git a/tests/label_v.html b/tests/label_v.html new file mode 100644 index 000000000..97c4730f0 --- /dev/null +++ b/tests/label_v.html @@ -0,0 +1,67 @@ + + + + demo + + + + +
    +

    This demo shows how you can create labels and ticks independently of one another.

    + + + From 051a854a82738473230fd1c20b6c9cacb036269d Mon Sep 17 00:00:00 2001 From: Steve Jones Date: Fri, 26 Aug 2016 17:48:09 +0200 Subject: [PATCH 11/54] Bug fix: indexFromSetName on invisible sets (#771) * indexFromSetName works with trailing invisible sets If the last set(s) have their visibility set to false, their names would not be added to `setIndexByName_`, so `indexFromSetName` would not be able to find them. This fixes that problem. * Corrected test. * Properly clone graph options --- auto_tests/tests/data_api.js | 18 ++++++++++++++++++ src/dygraph.js | 7 +++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/auto_tests/tests/data_api.js b/auto_tests/tests/data_api.js index e692fc61e..631990980 100644 --- a/auto_tests/tests/data_api.js +++ b/auto_tests/tests/data_api.js @@ -4,6 +4,7 @@ * @author danvdk@gmail.com (Dan Vanderkam) */ import Dygraph from '../../src/dygraph'; +import * as utils from '../../src/dygraph-utils'; describe("data-api", function() { cleanupAfterEach(); @@ -99,4 +100,21 @@ it('testGetRowForXDuplicates', function() { assert.equal(5, g.getRowForX(9)); }); +// indexFromSeriesName should return a value even if the series is invisible +// In 1.1.1, if you request the last set and it's invisible, the method returns undefined. +it('testIndexFromSetNameOnInvisibleSet', function() { + + var localOpts = utils.clone(opts); + localOpts.visibility = [true, false]; + + var g = new Dygraph(graphDiv, [ + "x,y1,y2", + "1,1,1", + "2,2,2", + "3,3,3" + ].join('\n'), localOpts); + + assert.equal(2, g.indexFromSetName("y2")); +}); + }); diff --git a/src/dygraph.js b/src/dygraph.js index e5053ba15..ff3bcb666 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -2304,16 +2304,15 @@ Dygraph.prototype.drawGraph_ = function() { this.setIndexByName_ = {}; var labels = this.attr_("labels"); - if (labels.length > 0) { - this.setIndexByName_[labels[0]] = 0; - } var dataIdx = 0; for (var i = 1; i < points.length; i++) { - this.setIndexByName_[labels[i]] = i; if (!this.visibility()[i - 1]) continue; this.layout_.addDataset(labels[i], points[i]); this.datasetIndex_[i] = dataIdx++; } + for (var i = 0; i < labels.length; i++) { + this.setIndexByName_[labels[i]] = i; + } this.computeYAxisRanges_(extremes); this.layout_.setYAxes(this.axes_); From 8cc4108bdb0db5006d794be50d1bbca9558373e9 Mon Sep 17 00:00:00 2001 From: Majlen Date: Mon, 12 Sep 2016 17:43:49 +0200 Subject: [PATCH 12/54] Check that setRow is not negative, fixes #644. (#773) Synchronization breaks up if this case is not checked. Fix has been proposed in the bugreport. --- src/dygraph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dygraph.js b/src/dygraph.js index ff3bcb666..3ffc2e6cd 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -1813,7 +1813,7 @@ Dygraph.prototype.setSelection = function(row, opt_seriesName, opt_locked) { // for. If it is, just use it, otherwise search the array for a point // in the proper place. var setRow = row - this.getLeftBoundary_(setIdx); - if (setRow < points.length && points[setRow].idx == row) { + if (setRow >= 0 && setRow < points.length && points[setRow].idx == row) { var point = points[setRow]; if (point.yval !== null) this.selPoints_.push(point); } else { From 2d0fdf6eb18eafde50830b8109f42e20b82247b1 Mon Sep 17 00:00:00 2001 From: Pierrick Koch Date: Thu, 15 Sep 2016 15:23:48 +0200 Subject: [PATCH 13/54] Dygraph.dateString_: shows milliseconds if any. (#774) * [utils] dateString_ display Milliseconds if any * [utils] fix dateAxisLabelFormatter milliseconds * [util] dateString_: compute ms in frac * [utils] clean hmsString_ format * [utils] add milliseconds padding in hmsString_ * [develop] add note on npm install * [tests] add labelsDateMilliseconds test * [utils] add millis in dateAxisLabelFormatter * [tests] fix requested changes in labelsDateMillis * [auto_tests] add date_formats testMillisecondsDate --- DEVELOP.md | 4 +++ auto_tests/tests/date_formats.js | 8 +++++ src/dygraph-utils.js | 15 ++++++--- tests/labelsDateMilliseconds.html | 56 +++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tests/labelsDateMilliseconds.html diff --git a/DEVELOP.md b/DEVELOP.md index 9a13888c9..6eb43fb19 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -6,6 +6,10 @@ This is a step-by-step guide explaining how to do it. ### How-to +To install dependencies, run + + npm install + To build dygraphs, run npm run build diff --git a/auto_tests/tests/date_formats.js b/auto_tests/tests/date_formats.js index f157b8dd4..5148fe7fb 100644 --- a/auto_tests/tests/date_formats.js +++ b/auto_tests/tests/date_formats.js @@ -36,4 +36,12 @@ it('testHyphenatedDate', function() { assert.equal(Date.UTC(2000, 1, 2), utils.dateParser(str)); }); +it('testMillisecondsDate', function() { + // Format: YYYY-MM-DD HH:MM:SS.MS + + // Midnight February 2, 2000 14:25:42.123 UTC + var ts = Date.UTC(2000, 1, 2, 14, 25, 42, 123); + assert.equal("2000/02/02 14:25:42.123", utils.dateString_(ts, true)); +}); + }); diff --git a/src/dygraph-utils.js b/src/dygraph-utils.js index 3a3e637b8..79215d4a5 100644 --- a/src/dygraph-utils.js +++ b/src/dygraph-utils.js @@ -362,10 +362,14 @@ export var DateAccessorsUTC = { * @return {string} A time of the form "HH:MM" or "HH:MM:SS" * @private */ -export function hmsString_(hh, mm, ss) { +export function hmsString_(hh, mm, ss, ms) { var ret = zeropad(hh) + ":" + zeropad(mm); if (ss) { ret += ":" + zeropad(ss); + if (ms) { + var str = "" + ms; + ret += "." + ('000'+str).substring(str.length); + } } return ret; }; @@ -387,16 +391,17 @@ export function dateString_(time, utc) { var hh = accessors.getHours(date); var mm = accessors.getMinutes(date); var ss = accessors.getSeconds(date); + var ms = accessors.getMilliseconds(date); // Get a year string: var year = "" + y; // Get a 0 padded month string var month = zeropad(m + 1); //months are 0-offset, sigh // Get a 0 padded day string var day = zeropad(d); - var frac = hh * 3600 + mm * 60 + ss; + var frac = hh * 3600 + mm * 60 + ss + 1e-3 * ms; var ret = year + "/" + month + "/" + day; if (frac) { - ret += " " + hmsString_(hh, mm, ss); + ret += " " + hmsString_(hh, mm, ss, ms); } return ret; }; @@ -1213,7 +1218,7 @@ export function dateAxisLabelFormatter(date, granularity, opts) { hours = accessors.getHours(date), mins = accessors.getMinutes(date), secs = accessors.getSeconds(date), - millis = accessors.getSeconds(date); + millis = accessors.getMilliseconds(date); if (granularity >= DygraphTickers.Granularity.DECADAL) { return '' + year; @@ -1225,7 +1230,7 @@ export function dateAxisLabelFormatter(date, granularity, opts) { // e.g. '21 Jan' (%d%b) return zeropad(day) + ' ' + SHORT_MONTH_NAMES_[month]; } else { - return hmsString_(hours, mins, secs); + return hmsString_(hours, mins, secs, millis); } } }; diff --git a/tests/labelsDateMilliseconds.html b/tests/labelsDateMilliseconds.html new file mode 100644 index 000000000..332e8c41f --- /dev/null +++ b/tests/labelsDateMilliseconds.html @@ -0,0 +1,56 @@ + + + + Milliseconds date labels + + + + + +

    Milliseconds display in date and time labels

    + +

    This shows how milliseconds are displayed when present.

    + +
    +
    + +

    You can check it by hovering over corresponding points and comparing + the value labels.

    + + + + + From f0e472002843b5e61aa9467f97f755280c91a46b Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 28 Sep 2016 08:45:38 -0400 Subject: [PATCH 14/54] Use CSS for styling --- auto_tests/coverage.html | 1 + auto_tests/runner.html | 1 + auto_tests/tests/axis_labels.js | 69 --------------- auto_tests/tests/pathological_cases.js | 1 - css/dygraph.css | 117 +++++++++++++++++++++++++ src/dygraph-default-attrs.js | 5 -- src/dygraph-options-reference.js | 18 ---- src/dygraph-utils.js | 3 - src/dygraph.js | 75 +++------------- src/plugins/annotations.js | 22 ++--- src/plugins/axes.js | 21 ++--- src/plugins/chart-labels.js | 16 +--- src/plugins/legend.js | 47 ++-------- 13 files changed, 156 insertions(+), 240 deletions(-) create mode 100644 css/dygraph.css diff --git a/auto_tests/coverage.html b/auto_tests/coverage.html index 04573478f..e8cd24ca4 100644 --- a/auto_tests/coverage.html +++ b/auto_tests/coverage.html @@ -3,6 +3,7 @@ dygraphs tests +
    diff --git a/auto_tests/runner.html b/auto_tests/runner.html index c3a3d8797..2f48d5b86 100644 --- a/auto_tests/runner.html +++ b/auto_tests/runner.html @@ -3,6 +3,7 @@ dygraphs tests +
    diff --git a/auto_tests/tests/axis_labels.js b/auto_tests/tests/axis_labels.js index c390392f2..5a631fa13 100644 --- a/auto_tests/tests/axis_labels.js +++ b/auto_tests/tests/axis_labels.js @@ -798,75 +798,6 @@ it('testAxisLabelFontSizeNull', function() { assertFontSize(document.querySelectorAll(".dygraph-axis-label-y"), "14px"); }); -it('testAxisLabelColor', function() { - var graph = document.getElementById("graph"); - var g = new Dygraph(graph, simpleData, {}); - - // Be sure we're dealing with a black default. - assert.equal("black", DEFAULT_ATTRS.axisLabelColor); - - var assertColor = function(selector, expected) { - Util.assertStyleOfChildren(selector, "color", expected); - } - - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(0, 0, 0)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y"), "rgb(0, 0, 0)"); - - g.updateOptions({ axisLabelColor : "red"}); - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(255, 0, 0)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y"), "rgb(255, 0, 0)"); - - g.updateOptions({ - axisLabelColor : null, - axes : { - x : { axisLabelColor : "blue" }, - } - }); - - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(0, 0, 255)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y"), "rgb(0, 0, 0)"); - - g.updateOptions({ - axes : { - y : { axisLabelColor : "green" }, - } - }); - - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(0, 0, 255)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y"), "rgb(0, 128, 0)"); - - g.updateOptions({ - series : { - Y2 : { axis : "y2" } // copy y2 series to y2 axis. - }, - axes : { - y2 : { axisLabelColor : "yellow" }, - } - }); - - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(0, 0, 255)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y1"), "rgb(0, 128, 0)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y2"), "rgb(255, 255, 0)"); -}); - -it('testAxisLabelColorNull', function() { - var graph = document.getElementById("graph"); - var g = new Dygraph(graph, simpleData, - { - axisLabelColor: null - }); - - var assertColor = function(selector, expected) { - Util.assertStyleOfChildren(selector, "color", expected); - } - - // Be sure we're dealing with a 14-point default. - assert.equal(14, DEFAULT_ATTRS.axisLabelFontSize); - - assertColor(document.querySelectorAll(".dygraph-axis-label-x"), "rgb(0, 0, 0)"); - assertColor(document.querySelectorAll(".dygraph-axis-label-y"), "rgb(0, 0, 0)"); -}); - /* * This test shows that the label formatter overrides labelsKMB for all values. */ diff --git a/auto_tests/tests/pathological_cases.js b/auto_tests/tests/pathological_cases.js index 0bcab0b79..0fab2008c 100644 --- a/auto_tests/tests/pathological_cases.js +++ b/auto_tests/tests/pathological_cases.js @@ -90,7 +90,6 @@ it('testCombinations', function() { var opts = { width: 300, height: 150, - labelsDivWidth: 100, pointSize: 10 }; for (var key in base) { diff --git a/css/dygraph.css b/css/dygraph.css new file mode 100644 index 000000000..75d58685f --- /dev/null +++ b/css/dygraph.css @@ -0,0 +1,117 @@ +/** + * Default styles for the dygraphs charting library. + */ + +.dygraph-legend { + position: absolute; + font-size: 14px; + z-index: 10; + width: 250px; /* labelsDivWidth */ + /* + dygraphs determines these based on the presence of chart labels. + It might make more sense to create a wrapper div around the chart proper. + top: 0px; + right: 2px; + */ + background: white; + line-height: normal; + text-align: left; + overflow: hidden; +} + +/* styles for a solid line in the legend */ +.dygraph-legend-line { + display: inline-block; + position: relative; + bottom: .5ex; + padding-left: 1em; + height: 1px; + border-bottom-width: 2px; + border-bottom-style: solid; + /* border-bottom-color is set based on the series color */ +} + +/* styles for a dashed line in the legend, e.g. when strokePattern is set */ +.dygraph-legend-dash { + display: inline-block; + position: relative; + bottom: .5ex; + height: 1px; + border-bottom-width: 2px; + border-bottom-style: solid; + /* border-bottom-color is set based on the series color */ + /* margin-right is set based on the stroke pattern */ + /* padding-left is set based on the stroke pattern */ +} + +.dygraph-roller { + position: absolute; + z-index: 10; +} + +/* This class is shared by all annotations, including those with icons */ +.dygraph-annotation { + position: absolute; + z-index: 10; + overflow: hidden; +} + +/* This class only applies to annotations without icons */ +/* Old class name: .dygraphDefaultAnnotation */ +.dygraph-default-annotation { + border: 1px solid black; + background-color: white; + text-align: center; +} + +.dygraph-axis-label { + /* position: absolute; */ + /* font-size: 14px; */ + z-index: 10; + line-height: normal; + overflow: hidden; + color: black; /* replaces old axisLabelColor option */ +} + +.dygraph-axis-label-x { +} + +.dygraph-axis-label-y { +} + +.dygraph-axis-label-y2 { +} + +.dygraph-title { + font-weight: bold; + z-index: 10; + text-align: center; + /* font-size: based on titleHeight option */ +} + +.dygraph-xlabel { + text-align: center; + /* font-size: based on xLabelHeight option */ +} + +/* For y-axis label */ +.dygraph-label-rotate-left { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(90deg); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -o-transform: rotate(90deg); + -ms-transform: rotate(90deg); +} + +/* For y2-axis label */ +.dygraph-label-rotate-right { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(-90deg); + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); +} diff --git a/src/dygraph-default-attrs.js b/src/dygraph-default-attrs.js index 5b7cb32f9..36cbd3e7f 100644 --- a/src/dygraph-default-attrs.js +++ b/src/dygraph-default-attrs.js @@ -12,10 +12,6 @@ var DEFAULT_ATTRS = { highlightSeriesBackgroundAlpha: 0.5, highlightSeriesBackgroundColor: 'rgb(255, 255, 255)', - labelsDivWidth: 250, - labelsDivStyles: { - // TODO(danvk): move defaults from createStatusMessage_ here. - }, labelsSeparateLines: false, labelsShowZeroValues: true, labelsKMB: false, @@ -67,7 +63,6 @@ var DEFAULT_ATTRS = { axisLineColor: "black", axisLineWidth: 0.3, gridLineWidth: 0.3, - axisLabelColor: "black", axisLabelWidth: 50, gridLineColor: "rgb(128,128,128)", diff --git a/src/dygraph-options-reference.js b/src/dygraph-options-reference.js index 4b1a23bf6..73615c21d 100644 --- a/src/dygraph-options-reference.js +++ b/src/dygraph-options-reference.js @@ -41,12 +41,6 @@ OPTIONS_REFERENCE = // "type": "integer", "description": "The size of the dot to draw on each point in pixels (see drawPoints). A dot is always drawn when a point is \"isolated\", i.e. there is a missing point on either side of it. This also controls the size of those dots." }, - "labelsDivStyles": { - "default": "null", - "labels": ["Legend"], - "type": "{}", - "description": "Additional styles to apply to the currently-highlighted points div. For example, { 'fontWeight': 'bold' } will make the labels bold. In general, it is better to use CSS to style the .dygraph-legend class than to use this property." - }, "drawPoints": { "default": "false", "labels": ["Data Line display"], @@ -439,12 +433,6 @@ OPTIONS_REFERENCE = // "example": "[10, 110]", "description": "Explicitly set the vertical range of the graph to [low, high]. This may be set on a per-axis basis to define each y-axis separately. If either limit is unspecified, it will be calculated automatically (e.g. [null, 30] to automatically calculate just the lower bound)" }, - "labelsDivWidth": { - "default": "250", - "labels": ["Legend"], - "type": "integer", - "description": "Width (in pixels) of the div which shows information on the currently-highlighted points." - }, "colorSaturation": { "default": "1.0", "labels": ["Data Series Colors"], @@ -695,12 +683,6 @@ OPTIONS_REFERENCE = // "type": "float (0.0 - 1.0)", "description" : "Error bars (or custom bars) for each series are drawn in the same color as the series, but with partial transparency. This sets the transparency. A value of 0.0 means that the error bars will not be drawn, whereas a value of 1.0 means that the error bars will be as dark as the line for the series itself. This can be used to produce chart lines whose thickness varies at each point." }, - "axisLabelColor": { - "default": "black", - "labels": ["Axis display"], - "type": "string", - "description" : "Color for x- and y-axis labels. This is a CSS color string." - }, "axisLabelWidth": { "default": "50 (y-axis), 60 (x-axis)", "labels": ["Axis display", "Chart labels"], diff --git a/src/dygraph-utils.js b/src/dygraph-utils.js index 79215d4a5..8e972a6f1 100644 --- a/src/dygraph-utils.js +++ b/src/dygraph-utils.js @@ -837,7 +837,6 @@ var pixelSafeOptions = { 'annotationDblClickHandler': true, 'annotationMouseOutHandler': true, 'annotationMouseOverHandler': true, - 'axisLabelColor': true, 'axisLineColor': true, 'axisLineWidth': true, 'clickCallback': true, @@ -855,8 +854,6 @@ var pixelSafeOptions = { 'interactionModel': true, 'isZoomedIgnoreProgrammaticZoom': true, 'labelsDiv': true, - 'labelsDivStyles': true, - 'labelsDivWidth': true, 'labelsKMB': true, 'labelsKMG2': true, 'labelsSeparateLines': true, diff --git a/src/dygraph.js b/src/dygraph.js index 3ffc2e6cd..ce9f11072 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -1029,32 +1029,28 @@ Dygraph.prototype.getPropertiesForSeries = function(series_name) { */ Dygraph.prototype.createRollInterface_ = function() { // Create a roller if one doesn't exist already. - if (!this.roller_) { - this.roller_ = document.createElement("input"); - this.roller_.type = "text"; - this.roller_.style.display = "none"; - this.graphDiv.appendChild(this.roller_); + var roller = this.roller_; + if (!roller) { + this.roller_ = roller = document.createElement("input"); + roller.type = "text"; + roller.style.display = "none"; + roller.className = 'dygraph-roller'; + this.graphDiv.appendChild(roller); } var display = this.getBooleanOption('showRoller') ? 'block' : 'none'; - var area = this.plotter_.area; - var textAttr = { "position": "absolute", - "zIndex": 10, + var area = this.getArea(); + var textAttr = { "top": (area.y + area.h - 25) + "px", "left": (area.x + 1) + "px", "display": display - }; - this.roller_.size = "2"; - this.roller_.value = this.rollPeriod_; - for (var name in textAttr) { - if (textAttr.hasOwnProperty(name)) { - this.roller_.style[name] = textAttr[name]; - } - } + }; + roller.size = "2"; + roller.value = this.rollPeriod_; + utils.update(roller.style, textAttr); - var dygraph = this; - this.roller_.onchange = function() { dygraph.adjustRoll(dygraph.roller_.value); }; + roller.onchange = () => this.adjustRoll(roller.value); }; /** @@ -3340,7 +3336,6 @@ Dygraph.prototype.size = function() { */ Dygraph.prototype.setAnnotations = function(ann, suppressDraw) { // Only add the annotation CSS rule once we know it will be used. - Dygraph.addAnnotationRule(); this.annotations_ = ann; if (!this.layout_) { console.warn("Tried to setAnnotations before dygraph was ready. " + @@ -3430,48 +3425,6 @@ Dygraph.prototype.ready = function(callback) { } }; -/** - * @private - * Adds a default style for the annotation CSS classes to the document. This is - * only executed when annotations are actually used. It is designed to only be - * called once -- all calls after the first will return immediately. - */ -Dygraph.addAnnotationRule = function() { - // TODO(danvk): move this function into plugins/annotations.js? - if (Dygraph.addedAnnotationCSS) return; - - var rule = "border: 1px solid black; " + - "background-color: white; " + - "text-align: center;"; - - var styleSheetElement = document.createElement("style"); - styleSheetElement.type = "text/css"; - document.getElementsByTagName("head")[0].appendChild(styleSheetElement); - - // Find the first style sheet that we can access. - // We may not add a rule to a style sheet from another domain for security - // reasons. This sometimes comes up when using gviz, since the Google gviz JS - // adds its own style sheets from google.com. - for (var i = 0; i < document.styleSheets.length; i++) { - if (document.styleSheets[i].disabled) continue; - var mysheet = document.styleSheets[i]; - try { - if (mysheet.insertRule) { // Firefox - var idx = mysheet.cssRules ? mysheet.cssRules.length : 0; - mysheet.insertRule(".dygraphDefaultAnnotation { " + rule + " }", idx); - } else if (mysheet.addRule) { // IE - mysheet.addRule(".dygraphDefaultAnnotation", rule); - } - Dygraph.addedAnnotationCSS = true; - return; - } catch(err) { - // Was likely a security exception. - } - } - - console.warn("Unable to add default annotation CSS rule; display may be off."); -}; - /** * Add an event handler. This event handler is kept until the graph is * destroyed with a call to graph.destroy(). diff --git a/src/plugins/annotations.js b/src/plugins/annotations.js index 46d08918e..87153c815 100644 --- a/src/plugins/annotations.js +++ b/src/plugins/annotations.js @@ -56,12 +56,6 @@ annotations.prototype.didDrawChart = function(e) { if (!points || points.length === 0) return; var containerDiv = e.canvas.parentNode; - var annotationStyle = { - "position": "absolute", - "fontSize": g.getOption('axisLabelFontSize') + "px", - "zIndex": 10, - "overflow": "hidden" - }; var bindEvt = function(eventName, classEventName, pt) { return function(annotation_event) { @@ -75,7 +69,7 @@ annotations.prototype.didDrawChart = function(e) { }; // Add the annotations one-by-one. - var area = e.dygraph.plotter_.area; + var area = e.dygraph.getArea(); // x-coord to sum of previous annotation's heights (used for stacking). var xToUsedHeight = {}; @@ -93,18 +87,18 @@ annotations.prototype.didDrawChart = function(e) { tick_height = a.tickHeight; } + // TODO: deprecate axisLabelFontSize in favor of CSS var div = document.createElement("div"); - for (var name in annotationStyle) { - if (annotationStyle.hasOwnProperty(name)) { - div.style[name] = annotationStyle[name]; - } - } + div.style['fontSize'] = g.getOption('axisLabelFontSize') + "px"; + var className = 'dygraph-annotation'; if (!a.hasOwnProperty('icon')) { - div.className = "dygraphDefaultAnnotation"; + // camelCase class names are deprecated. + className += ' dygraphDefaultAnnotation dygraph-default-annotation'; } if (a.hasOwnProperty('cssClass')) { - div.className += " " + a.cssClass; + className += " " + a.cssClass; } + div.className = className; var width = a.hasOwnProperty('width') ? a.width : 16; var height = a.hasOwnProperty('height') ? a.height : 16; diff --git a/src/plugins/axes.js b/src/plugins/axes.js index f93f36fce..2d9e31f92 100644 --- a/src/plugins/axes.js +++ b/src/plugins/axes.js @@ -19,6 +19,8 @@ Options left to make axis-friendly. ('xAxisHeight') */ +import * as utils from '../dygraph-utils'; + /** * Draws the axes. This includes the labels on the x- and y-axes, as well * as the tick marks on the axes. @@ -115,19 +117,14 @@ axes.prototype.willDrawChart = function(e) { return { position: 'absolute', fontSize: g.getOptionForAxis('axisLabelFontSize', axis) + 'px', - zIndex: 10, - color: g.getOptionForAxis('axisLabelColor', axis), width: g.getOptionForAxis('axisLabelWidth', axis) + 'px', - // height: g.getOptionForAxis('axisLabelFontSize', 'x') + 2 + "px", - lineHeight: 'normal', // Something other than "normal" line-height screws up label positioning. - overflow: 'hidden' }; }; var labelStyles = { - x : makeLabelStyle('x'), - y : makeLabelStyle('y'), - y2 : makeLabelStyle('y2') + x: makeLabelStyle('x'), + y: makeLabelStyle('y'), + y2: makeLabelStyle('y2') }; var makeDiv = function(txt, axis, prec_axis) { @@ -139,11 +136,8 @@ axes.prototype.willDrawChart = function(e) { */ var div = document.createElement('div'); var labelStyle = labelStyles[prec_axis == 'y2' ? 'y2' : axis]; - for (var name in labelStyle) { - if (labelStyle.hasOwnProperty(name)) { - div.style[name] = labelStyle[name]; - } - } + utils.update(div.style, labelStyle); + // TODO: combine outer & inner divs var inner_div = document.createElement('div'); inner_div.className = 'dygraph-axis-label' + ' dygraph-axis-label-' + axis + @@ -202,6 +196,7 @@ axes.prototype.willDrawChart = function(e) { } else { label.style.top = top + 'px'; } + // TODO: replace these with css classes? if (tick.axis === 0) { label.style.left = (area.x - getAxisOption('axisLabelWidth') - getAxisOption('axisTickSize')) + 'px'; label.style.textAlign = 'right'; diff --git a/src/plugins/chart-labels.js b/src/plugins/chart-labels.js index 5fbbdc5c8..2d09fc837 100644 --- a/src/plugins/chart-labels.js +++ b/src/plugins/chart-labels.js @@ -79,16 +79,8 @@ var createRotatedDiv = function(g, box, axis, classes, html) { inner_div.style.height = box.w + 'px'; inner_div.style.top = (box.h / 2 - box.w / 2) + 'px'; inner_div.style.left = (box.w / 2 - box.h / 2) + 'px'; - inner_div.style.textAlign = 'center'; - - // CSS rotation is an HTML5 feature which is not standardized. Hence every - // browser has its own name for the CSS style. - var val = 'rotate(' + (axis == 1 ? '-' : '') + '90deg)'; - inner_div.style.transform = val; // HTML5 - inner_div.style.WebkitTransform = val; // Safari/Chrome - inner_div.style.MozTransform = val; // Firefox - inner_div.style.OTransform = val; // Opera - inner_div.style.msTransform = val; // IE9 + // TODO: combine inner_div and class_div. + inner_div.className = 'dygraph-label-rotate-' + (axis == 1 ? 'right' : 'left'); var class_div = document.createElement("div"); class_div.className = classes; @@ -108,10 +100,7 @@ chart_labels.prototype.layout = function(e) { // QUESTION: should this return an absolutely-positioned div instead? var title_rect = e.reserveSpaceTop(g.getOption('titleHeight')); this.title_div_ = createDivInRect(title_rect); - this.title_div_.style.textAlign = 'center'; this.title_div_.style.fontSize = (g.getOption('titleHeight') - 8) + 'px'; - this.title_div_.style.fontWeight = 'bold'; - this.title_div_.style.zIndex = 10; var class_div = document.createElement("div"); class_div.className = 'dygraph-label dygraph-title'; @@ -123,7 +112,6 @@ chart_labels.prototype.layout = function(e) { if (g.getOption('xlabel')) { var x_rect = e.reserveSpaceBottom(g.getOption('xLabelHeight')); this.xlabel_div_ = createDivInRect(x_rect); - this.xlabel_div_.style.textAlign = 'center'; this.xlabel_div_.style.fontSize = (g.getOption('xLabelHeight') - 2) + 'px'; var class_div = document.createElement("div"); diff --git a/src/plugins/legend.js b/src/plugins/legend.js index 96e68f433..8b9184120 100644 --- a/src/plugins/legend.js +++ b/src/plugins/legend.js @@ -35,9 +35,6 @@ Legend.prototype.toString = function() { return "Legend Plugin"; }; -// (defined below) -var generateLegendDashHTML; - /** * This is called during the dygraph constructor, after options have been set * but before the data is available. @@ -52,7 +49,6 @@ var generateLegendDashHTML; */ Legend.prototype.activate = function(g) { var div; - var divWidth = g.getOption('labelsDivWidth'); var userLabelsDiv = g.getOption('labelsDiv'); if (userLabelsDiv && null !== userLabelsDiv) { @@ -62,35 +58,8 @@ Legend.prototype.activate = function(g) { div = userLabelsDiv; } } else { - // Default legend styles. These can be overridden in CSS by adding - // "!important" after your rule, e.g. "left: 30px !important;" - var messagestyle = { - "position": "absolute", - "fontSize": "14px", - "zIndex": 10, - "width": divWidth + "px", - "top": "0px", - "left": (g.size().width - divWidth - 2) + "px", - "background": "white", - "lineHeight": "normal", - "textAlign": "left", - "overflow": "hidden"}; - - // TODO(danvk): get rid of labelsDivStyles? CSS is better. - utils.update(messagestyle, g.getOption('labelsDivStyles')); div = document.createElement("div"); div.className = "dygraph-legend"; - for (var name in messagestyle) { - if (!messagestyle.hasOwnProperty(name)) continue; - - try { - div.style[name] = messagestyle[name]; - } catch (e) { - console.warn("You are using unsupported css properties for your " + - "browser in labelsDivStyles"); - } - } - // TODO(danvk): come up with a cleaner way to expose this. g.graphDiv.appendChild(div); this.is_generated_div_ = true; @@ -136,7 +105,7 @@ Legend.prototype.select = function(e) { if (legendMode === 'follow') { // create floating legend div var area = e.dygraph.plotter_.area; - var labelsDivWidth = e.dygraph.getOption('labelsDivWidth'); + var labelsDivWidth = this.legend_div.offsetWidth; var yAxisLabelWidth = e.dygraph.getOptionForAxis('axisLabelWidth', 'y'); // determine floating [left, top] coordinates of the legend div // within the plotter_ area @@ -195,10 +164,9 @@ Legend.prototype.predraw = function(e) { // TODO(danvk): only use real APIs for this. e.dygraph.graphDiv.appendChild(this.legend_div_); var area = e.dygraph.getArea(); - var labelsDivWidth = e.dygraph.getOption("labelsDivWidth"); + var labelsDivWidth = this.legend_div_.offsetWidth; this.legend_div_.style.left = area.x + area.w - labelsDivWidth - 1 + "px"; this.legend_div_.style.top = area.y + "px"; - this.legend_div_.style.width = labelsDivWidth + "px"; }; /** @@ -341,12 +309,10 @@ Legend.defaultFormatter = function(data) { * @private */ // TODO(danvk): cache the results of this -generateLegendDashHTML = function(strokePattern, color, oneEmWidth) { +function generateLegendDashHTML(strokePattern, color, oneEmWidth) { // Easy, common case: a solid line if (!strokePattern || strokePattern.length <= 1) { - return "
    "; + return `
    `; } var i, j, paddingLeft, marginRight; @@ -393,10 +359,7 @@ generateLegendDashHTML = function(strokePattern, color, oneEmWidth) { // The repeated first segment has no right margin. marginRight = 0; } - dash += "
    "; + dash += `
    `; } } return dash; From 93a5bb4c827d6665f395c48b216438f95e94d76e Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 28 Sep 2016 08:45:57 -0400 Subject: [PATCH 15/54] Use CSS for tests, gallery and docs --- docs/annotations.html | 4 +++- gallery/border.js | 2 +- gallery/edge-padding.js | 2 +- gallery/index.html | 1 + gallery/range-selector.js | 9 ++++---- gallery/styled-chart-labels.js | 9 +------- gallery/temperature-sf-ny.js | 3 +-- tests/annotation-native.html | 1 + tests/annotation.html | 1 + tests/avoidMinZero.html | 1 + tests/border.html | 5 ++++- tests/callback.html | 1 + tests/century-scale.html | 1 + tests/charting-combinations.html | 1 + tests/color-cycle.html | 1 + tests/color-visibility.html | 1 + tests/connect-separated.html | 1 + tests/crosshair.html | 1 + tests/css-positioning.html | 1 + tests/custom-bars.html | 1 + tests/custom-circles.html | 1 + tests/customLabel.html | 1 + tests/customLabelCss3.html | 19 +++++++++------- tests/dateWindow.html | 1 + tests/daylight-savings.html | 1 + tests/demo.html | 1 + tests/dense-fill.html | 1 + tests/draw-points.html | 1 + tests/drawing.html | 1 + tests/dygraph-many-points-benchmark.html | 1 + tests/dygraph.html | 1 + tests/dynamic-update.html | 1 + tests/exported-symbols.html | 1 + tests/fillGraph-alpha.html | 1 + tests/fillGraph.html | 1 + tests/fractions.html | 1 + tests/grid_dot.html | 1 + tests/gviz-infinity.html | 1 + tests/gviz-selection.html | 1 + tests/gviz.html | 1 + tests/hairlines.html | 1 + tests/highlighted-region.html | 1 + tests/hourly.html | 1 + tests/iframe.html | 1 + tests/independent-series.html | 1 + tests/interaction.html | 1 + tests/is-zoomed-ignore-programmatic-zoom.html | 1 + tests/is-zoomed.html | 1 + tests/isolated-points.html | 1 + tests/label-div.html | 1 + tests/labelsDateUTC.html | 1 + tests/labelsKMB.html | 1 + tests/layout-options.html | 1 + tests/legend-formatter.html | 1 + tests/legend-values.html | 3 ++- tests/linear-regression-addseries.html | 1 + tests/linear-regression-fractions.html | 1 + tests/linear-regression.html | 1 + tests/link-interaction.html | 1 + tests/logscale.html | 1 + tests/missing-data.html | 1 + tests/multi-scale.html | 1 + tests/native-format.html | 1 + tests/negative.html | 1 + tests/no-range.html | 1 + tests/no-visibility.html | 1 + tests/number-format.html | 1 + tests/numeric-axis.html | 1 + tests/numeric-gviz.html | 1 + tests/out-of-order.html | 1 + tests/per-series.html | 1 + tests/perf.html | 1 + tests/plotter.html | 1 + tests/plotters.html | 1 + tests/plugins.html | 1 + tests/range-selector.html | 22 ++++++++++++++----- tests/resize.html | 1 + tests/reverse-y-axis.html | 1 + tests/series-highlight.html | 1 + tests/small-range-zero.html | 1 + tests/smooth-plots.html | 1 + tests/spacing.html | 1 + tests/stacked.html | 1 + tests/steps.html | 1 + tests/stock.html | 1 + tests/straw-broom.html | 1 + tests/styled-chart-labels.html | 13 +++++------ tests/synchronize.html | 1 + tests/temperature-sf-ny.html | 6 +++-- tests/two-axes-vr.html | 1 + tests/two-axes.html | 1 + tests/unboxed-spark.html | 1 + tests/underlay-callback.html | 1 + tests/value-axis-formatters.html | 1 + tests/visibility.html | 1 + tests/x-axis-formatter.html | 1 + tests/zero-series.html | 1 + tests/zoom.html | 1 + 98 files changed, 140 insertions(+), 43 deletions(-) diff --git a/docs/annotations.html b/docs/annotations.html index 0a3ba17c4..9ed49b153 100644 --- a/docs/annotations.html +++ b/docs/annotations.html @@ -6,6 +6,9 @@ .annotation { font-size: 12px !important; } + .dygraph-legend { + width: 300px; + }

    dygraphs Annotations

    @@ -26,7 +29,6 @@

    Demo: Dow Jones Industrial Average

    showRoller: true, customBars: true, labelsKMB: true, - labelsDivWidth: 300 } ); diff --git a/gallery/border.js b/gallery/border.js index b5e4f6893..eacaf4681 100644 --- a/gallery/border.js +++ b/gallery/border.js @@ -6,12 +6,12 @@ Gallery.register( title: 'Graph stays within the border', setup: function(parent) { parent.innerHTML = + "" + "
    "; }, run: function() { new Dygraph(document.getElementById('bordered'), data, { - labelsDivStyles: { border: '1px solid black' }, title: 'Chart Title', xlabel: 'Date', ylabel: 'Temperature (F)' diff --git a/gallery/edge-padding.js b/gallery/edge-padding.js index be79054ba..5956d4a40 100644 --- a/gallery/edge-padding.js +++ b/gallery/edge-padding.js @@ -6,6 +6,7 @@ Gallery.register( title: 'Graph edge padding and axis position', setup: function(parent) { parent.innerHTML = ( + "" + "

    " + " Mode:" + " use {x,y}RangePad" + @@ -39,7 +40,6 @@ Gallery.register( var g = new Dygraph(gdiv, data, { labels: ['x', 'A', 'B'], - labelsDivWidth: 100, gridLineColor: '#ccc', includeZero: true, width: 250, diff --git a/gallery/index.html b/gallery/index.html index c953deb37..a749cf000 100644 --- a/gallery/index.html +++ b/gallery/index.html @@ -2,6 +2,7 @@ Dygraphs Gallery + diff --git a/gallery/range-selector.js b/gallery/range-selector.js index 09bfd49c3..e243b43b2 100644 --- a/gallery/range-selector.js +++ b/gallery/range-selector.js @@ -7,6 +7,11 @@ Gallery.register( title: 'Demo of the Range Selector', setup: function(parent) { parent.innerHTML = [ + "", "

    No roll period.

    ", "
    ", "", @@ -27,7 +32,6 @@ Gallery.register( title: 'Daily Temperatures in New York vs. San Francisco', ylabel: 'Temperature (F)', legend: 'always', - labelsDivStyles: { 'textAlign': 'right' }, showRangeSelector: true } ); @@ -41,7 +45,6 @@ Gallery.register( title: 'Daily Temperatures in New York vs. San Francisco', ylabel: 'Temperature (F)', legend: 'always', - labelsDivStyles: { 'textAlign': 'right' }, showRangeSelector: true, rangeSelectorHeight: 30, rangeSelectorPlotStrokeColor: 'yellow', @@ -58,11 +61,9 @@ Gallery.register( title: 'Nightly Temperatures in New York vs. San Francisco', ylabel: 'Temperature (F)', legend: 'always', - labelsDivStyles: { 'textAlign': 'right', 'backgroundColor': '#101015' }, showRangeSelector: true, rangeSelectorPlotFillColor: 'MediumSlateBlue', rangeSelectorPlotFillGradientColor: 'rgba(123, 104, 238, 0)', - axisLabelColor: 'white', colorValue: 0.9, fillAlpha: 0.4 } diff --git a/gallery/styled-chart-labels.js b/gallery/styled-chart-labels.js index 0268f6dcd..6f8c3b46a 100644 --- a/gallery/styled-chart-labels.js +++ b/gallery/styled-chart-labels.js @@ -6,6 +6,7 @@ Gallery.register( title: 'Each chart label is styled independently with CSS', setup: function(parent) { parent.innerHTML = [ + "", "

    This chart's labels are styled

    ", "
    ", "

    This version of the chart uses the default styles:

    ", @@ -21,10 +22,6 @@ Gallery.register( titleHeight: 32, ylabel: 'Temperature (F)', xlabel: 'Date (Ticks indicate the start of the indicated time period)', - labelsDivStyles: { - 'text-align': 'right', - 'background': 'none' - }, strokeWidth: 1.5 } ); @@ -37,10 +34,6 @@ Gallery.register( title: 'High and Low Temperatures (30-day average)', ylabel: 'Temperature (F)', xlabel: 'Date (Ticks indicate the start of the indicated time period)', - labelsDivStyles: { - 'text-align': 'right', - 'background': 'none' - }, strokeWidth: 1.5 } ); diff --git a/gallery/temperature-sf-ny.js b/gallery/temperature-sf-ny.js index f2c9ad134..7e4131016 100644 --- a/gallery/temperature-sf-ny.js +++ b/gallery/temperature-sf-ny.js @@ -8,6 +8,7 @@ Gallery.register( title: 'Demo of a graph with many data points and custom error bars.', setup: function(parent) { parent.innerHTML = [ + "", "

    Roll period of 14 timesteps.

    ", "
    ", "

    No roll period.

    ", @@ -23,7 +24,6 @@ Gallery.register( title: 'Daily Temperatures in New York vs. San Francisco', ylabel: 'Temperature (F)', legend: 'always', - labelsDivStyles: { 'textAlign': 'right' } } ); new Dygraph( @@ -36,7 +36,6 @@ Gallery.register( title: 'Daily Temperatures in New York vs. San Francisco', ylabel: 'Temperature (F)', legend: 'always', - labelsDivStyles: { 'textAlign': 'right' } } ); } diff --git a/tests/annotation-native.html b/tests/annotation-native.html index a00349706..4e4538d87 100644 --- a/tests/annotation-native.html +++ b/tests/annotation-native.html @@ -1,6 +1,7 @@ + Native format annotations diff --git a/tests/annotation.html b/tests/annotation.html index 6d477e235..4cdcb101a 100644 --- a/tests/annotation.html +++ b/tests/annotation.html @@ -1,6 +1,7 @@ + demo - - - - - - -

    isZoomedIgnoreProgrammaticZoom Option

    -

    - By default, when the dateWindow or updateOptions - of a chart is changed programmatically by a call to updateOptions - the zoomed flags (isZoomed) are changed. This is the same - as manually zooming in using the mouse. -

    -

    - Sometimes it may be desirable to change the display of the chart by - manipulating the dateWindow and valueRange - options but without changing the zoomed flags, for example where manual - zooming is still required but where it is also desired that the zoomed - flags drive display elements, but only for manual zooming. -

    -

    - In this case isZoomedIgnoreProgrammaticZoom may be specified along with - either the dateWindow or valueRange values to - updateOptions and the zoomed flags will remain unaffected. -

    -

    - The chart below may be manipulated to change the updateOptions - using the Max and Min Y axis buttons and the dateWindow - by using the Max and Min X axis buttons. -

    -

    - Toggle the check box below to determine the difference in operation of the zoom flags - when the date and value windows of the chart are changed using the arrows underneath. -

    -

    Do not change zoom flags (isZoomedIgnoreProgrammaticZoom)

    - -
    -
    -

    - Max Y Axis: - - -

    -

    - Min Y Axis: - - -

    -

    - Min X Axis: - - -

    -

    - Max X Axis: - - -

    -
    -
    -
    - -
    -
    -
    -

    Zoomed Flags

    -

    Zoomed: False

    -

    Zoomed X: False

    -

    Zoomed Y: False

    -

    Window coordinates (in dates and values):

    -
    -
    -
    - - - - diff --git a/tests/is-zoomed.html b/tests/is-zoomed.html index 1becb2e2b..28c52cf98 100644 --- a/tests/is-zoomed.html +++ b/tests/is-zoomed.html @@ -1,7 +1,7 @@ - isZoomedIgnoresProgrammaticZoom Flag + isZoomed method - - diff --git a/auto_tests/runner.html b/auto_tests/runner.html index 2f48d5b86..7ceb0d08c 100644 --- a/auto_tests/runner.html +++ b/auto_tests/runner.html @@ -9,9 +9,6 @@
    - - - diff --git a/auto_tests/tests/xhr.js b/auto_tests/tests/xhr.js index 90712fadb..ba06e61a7 100644 --- a/auto_tests/tests/xhr.js +++ b/auto_tests/tests/xhr.js @@ -14,6 +14,8 @@ import Dygraph from '../../src/dygraph'; import Util from './Util'; +import 'core-js/es6/promise'; + function dygraphPromise(div, data, opts) { return new Promise((resolve, reject) => { const g = new Dygraph(div, data, opts); diff --git a/package.json b/package.json index 48b653442..c5a8d0b31 100644 --- a/package.json +++ b/package.json @@ -60,5 +60,8 @@ }, "pre-commit": [ "tests-ok" - ] + ], + "dependencies": { + "core-js": "^2.4.1" + } } diff --git a/scripts/build.sh b/scripts/build.sh index 9374a9c0b..35159e4aa 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -34,7 +34,7 @@ browserify \ # Create dist/dygraph.tmp.js.map cat dist/dygraph.tmp.js | exorcist --base . dist/dygraph.tmp.js.map > /dev/null -header='/*! @license Copyright 2014 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */' +header='/*! @license Copyright 2017 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */' # Create dist/dygraph.js.min{,.map} uglifyjs --compress --mangle \ diff --git a/src/dygraph.js b/src/dygraph.js index 13c67441d..d1629dbfb 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -43,6 +43,10 @@ */ +// Polyfills +import 'core-js/es6/symbol'; +import 'core-js/fn/symbol/iterator'; + import DygraphLayout from './dygraph-layout'; import DygraphCanvasRenderer from './dygraph-canvas'; import DygraphOptions from './dygraph-options'; From fd6b8dadbaa0614671bef1508c23d6a932e25081 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 28 Dec 2016 16:37:08 -0500 Subject: [PATCH 27/54] 2.0.0 release fixes (#815) * Documentation / test cleanup * Remove deprecated avoidMinZero option * remove all references to dygraph-combined * Drop for..of and polyfill to save space * Check for strings in native format * Generate minified CSS * Get npm distribution working * Guard process access for rollup * Add ES6 example to home page * Update tests to source CSS from dist * update some references * Drop bower, bump version * index.es5.js * bump version --- .github/CONTRIBUTING.md | 4 +- .github/ISSUE_TEMPLATE.md | 4 +- .gitignore | 1 + README.md | 3 +- auto_tests/tests/formats.js | 10 +++ auto_tests/tests/pathological_cases.js | 4 -- auto_tests/tests/range_tests.js | 44 +++---------- bower.json | 37 ----------- docs/header.html | 5 +- docs/index.html | 16 ++++- docs/tutorial.html | 15 +++-- docs/versions.html | 10 ++- gallery/avoid-min-zero.js | 61 ----------------- gallery/edge-padding.js | 84 ------------------------ gallery/gallery.js | 2 +- gallery/index.html | 4 +- gwt/org/danvk/Dygraphs.java | 2 +- index.es5.js | 2 + index.js | 1 + package.json | 26 ++++---- releases.json | 15 +++++ scripts/build.sh | 17 ++--- scripts/generate-documentation.py | 2 +- scripts/generate-download.py | 19 +++--- scripts/generate-jsdoc.sh | 2 +- scripts/push-to-web.sh | 27 ++++---- scripts/release.sh | 25 ++----- scripts/weigh-in.sh | 2 +- src/dygraph-default-attrs.js | 1 - src/dygraph-options-reference.js | 10 +-- src/dygraph-options.js | 8 ++- src/dygraph.js | 65 ++++++++++-------- src/plugins/axes.js | 12 ++-- src/plugins/grid.js | 13 ++-- tests/annotation-gviz.html | 4 -- tests/annotation-native.html | 2 +- tests/annotation.html | 9 +-- tests/avoidMinZero.html | 81 ----------------------- tests/border.html | 6 +- tests/callback.html | 6 +- tests/century-scale.html | 6 +- tests/charting-combinations.html | 2 +- tests/color-cycle.html | 6 +- tests/color-visibility.html | 6 +- tests/connect-separated.html | 6 +- tests/crosshair.html | 6 +- tests/css-positioning.html | 2 +- tests/custom-bars.html | 6 +- tests/custom-circles.html | 6 +- tests/customLabel.html | 6 +- tests/customLabelCss3.html | 6 +- tests/dateWindow.html | 6 +- tests/daylight-savings.html | 6 +- tests/demo.html | 6 +- tests/dense-fill.html | 2 +- tests/draw-points.html | 6 +- tests/drawing.html | 6 +- tests/dygraph-many-points-benchmark.html | 6 +- tests/dygraph.html | 6 +- tests/dynamic-update.html | 6 +- tests/exported-symbols.html | 2 +- tests/fillGraph-alpha.html | 6 +- tests/fillGraph.html | 6 +- tests/fractions.html | 6 +- tests/grid_dot.html | 6 +- tests/gviz-infinity.html | 6 +- tests/gviz-selection.html | 6 +- tests/gviz.html | 6 +- tests/hairlines.html | 2 +- tests/highlighted-region.html | 6 +- tests/hourly.html | 6 +- tests/iframe.html | 2 +- tests/independent-series.html | 6 +- tests/interaction.html | 6 +- tests/is-zoomed.html | 6 +- tests/isolated-points.html | 6 +- tests/label-div.html | 6 +- tests/labelsDateMilliseconds.html | 4 -- tests/labelsDateUTC.html | 6 +- tests/labelsKMB.html | 6 +- tests/layout-options.html | 6 +- tests/legend-formatter.html | 2 +- tests/legend-values.html | 6 +- tests/linear-regression-addseries.html | 6 +- tests/linear-regression-fractions.html | 6 +- tests/linear-regression.html | 6 +- tests/link-interaction.html | 6 +- tests/logscale.html | 6 +- tests/missing-data.html | 6 +- tests/multi-scale.html | 2 +- tests/native-format.html | 14 ++-- tests/negative.html | 6 +- tests/no-range.html | 6 +- tests/no-visibility.html | 6 +- tests/number-format.html | 6 +- tests/numeric-axis.html | 6 +- tests/numeric-gviz.html | 6 +- tests/out-of-order.html | 6 +- tests/per-series.html | 38 +---------- tests/perf.html | 6 +- tests/plotter.html | 6 +- tests/plotters.html | 2 +- tests/plugins.html | 2 +- tests/range-selector.html | 6 +- tests/resize.html | 6 +- tests/reverse-y-axis.html | 6 +- tests/series-highlight.html | 6 +- tests/small-range-zero.html | 6 +- tests/smooth-plots.html | 2 +- tests/spacing.html | 6 +- tests/stacked.html | 6 +- tests/steps.html | 6 +- tests/stock.html | 6 +- tests/straw-broom.html | 2 +- tests/styled-chart-labels.html | 6 +- tests/synchronize.html | 6 +- tests/temperature-sf-ny.html | 6 +- tests/two-axes-vr.html | 6 +- tests/two-axes.html | 6 +- tests/unboxed-spark.html | 6 +- tests/underlay-callback.html | 6 +- tests/value-axis-formatters.html | 6 +- tests/visibility.html | 6 +- tests/x-axis-formatter.html | 6 +- tests/zero-series.html | 6 +- tests/zoom.html | 6 +- 126 files changed, 289 insertions(+), 878 deletions(-) delete mode 100644 bower.json delete mode 100644 gallery/avoid-min-zero.js delete mode 100644 gallery/edge-padding.js create mode 100644 index.es5.js create mode 100644 index.js delete mode 100644 tests/avoidMinZero.html diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index ee72da0ef..80d7cf27a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -7,13 +7,13 @@ It also helps if you include the non-compacted version of the JS on your page. For instance, instead of doing this: ```html - + ``` do this: ```html - + ``` This makes error messages and debugging simpler. The jsfiddle does this automatically. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 75d0c7a6d..3bbac0493 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -8,13 +8,13 @@ It also helps if you include the non-compacted version of the JS on your page. For instance, instead of doing this: ```html - + ``` do this: ```html - + ``` This makes error messages and debugging simpler. The jsfiddle does this automatically. diff --git a/.gitignore b/.gitignore index 121cd6678..e97dd1988 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ env dist coverage *.log +*.pyc diff --git a/README.md b/README.md index 9abb9a1a9..8e639e510 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ Get help with dygraphs on ```html - + +
    diff --git a/auto_tests/tests/formats.js b/auto_tests/tests/formats.js index f16cc6d88..2548d99fd 100644 --- a/auto_tests/tests/formats.js +++ b/auto_tests/tests/formats.js @@ -77,6 +77,16 @@ it('testXValueParser', function() { assert.equal(6, g.getValue(3, 0)); }); +it('should throw on strings in native format', () => { + assert.throws(() => { + new Dygraph('graph', [['1', '10'], ['2', '20']]) + }, /expected number or date/i); + + assert.throws(() => { + new Dygraph('graph', [[new Date(), '10'], [new Date(), '20']]) + }, /expected number or array/i); +}); + var assertData = function(g) { var expected = dataArray; diff --git a/auto_tests/tests/pathological_cases.js b/auto_tests/tests/pathological_cases.js index 0fab2008c..326fefb71 100644 --- a/auto_tests/tests/pathological_cases.js +++ b/auto_tests/tests/pathological_cases.js @@ -70,10 +70,6 @@ it('testCombinations', function() { var variantOpts = { none: {}, - avoidMinZero: { - avoidMinZero: true, - includeZero: true - }, padded: { includeZero: true, drawAxesAtZero: true, diff --git a/auto_tests/tests/range_tests.js b/auto_tests/tests/range_tests.js index 19d429478..f14d30fdb 100644 --- a/auto_tests/tests/range_tests.js +++ b/auto_tests/tests/range_tests.js @@ -19,7 +19,7 @@ // THE SOFTWARE. -/** +/** * @fileoverview Test valueRange and dateWindow changes. * * @author konigsberg@google.com (Robert Konigsberg) @@ -43,7 +43,7 @@ var ZERO_TO_FIFTY_STEPS = (function() { }()); var FIVE_TO_ONE_THOUSAND = [ - [ 1, 10 ], [ 2, 20 ], [ 3, 30 ], [ 4, 40 ] , [ 5, 50 ], + [ 1, 10 ], [ 2, 20 ], [ 3, 30 ], [ 4, 40 ] , [ 5, 50 ], [ 6, 60 ], [ 7, 70 ], [ 8, 80 ], [ 9, 90 ] , [ 10, 1000 ]]; describe("range-tests", function() { @@ -106,7 +106,7 @@ it('testRangeSetOperations', function() { g.updateOptions({ }); assert.deepEqual([12, 18], g.xAxisRange()); assert.deepEqual([10, 40], g.yAxisRange(0)); - + g.updateOptions({valueRange : null, axes: {y:{valueRange : [15, 20]}}}); assert.deepEqual([12, 18], g.xAxisRange()); assert.deepEqual([15, 20], g.yAxisRange(0)); @@ -182,7 +182,7 @@ it('testLogScaleExcludesZero', function() { labels: ['X', 'Y'] }); assert.deepEqual([10, 1099], g.yAxisRange(0)); - + g.updateOptions({ logscale : false }); assert.deepEqual([0, 1099], g.yAxisRange(0)); }); @@ -196,7 +196,7 @@ it('testIncludeZeroIncludesZero', function() { labels: ['X', 'Y'] }); assert.deepEqual([0, 1100], g.yAxisRange(0)); - + g.updateOptions({ includeZero : false }); assert.deepEqual([450, 1050], g.yAxisRange(0)); }); @@ -206,14 +206,14 @@ it('testIncludeZeroIncludesZero', function() { * Verify that includeZero range is properly specified per axis. */ it('testIncludeZeroPerAxis', function() { - var g = new Dygraph("graph", + var g = new Dygraph("graph", 'X,A,B\n'+ '0,50,50\n'+ '50,110,110\n', { drawPoints: true, pointSize:5, - series:{ + series:{ A: { axis: 'y', pointSize: 10 @@ -221,7 +221,7 @@ it('testIncludeZeroPerAxis', function() { B: { axis: 'y2' } - }, + }, axes: { 'y2': { includeZero: true } } @@ -242,7 +242,7 @@ it('testIncludeZeroPerAxis', function() { /** * Verify that very large Y ranges don't break things. - */ + */ it('testHugeRange', function() { var g = new Dygraph("graph", [[0, -1e120], [1, 1e230]], { includeZero: true, @@ -252,15 +252,6 @@ it('testHugeRange', function() { assert.closeTo(1, 1.1e230 / g.yAxisRange(0)[1], 0.001); }); -/** - * Verify old-style avoidMinZero option. - */ -it('testAvoidMinZero', function() { - var g = createGraph({ - avoidMinZero: true, - }, ZERO_TO_FIFTY_STEPS, [10, 20], [-5, 55]); -}); - /** * Verify ranges with user-specified padding, implicit avoidMinZero. */ @@ -345,23 +336,6 @@ it('testLogscalePad', function() { [-10, 30], [5.623, 1778.279]); }); -/** - * Verify scrolling all-zero region, traditional. - */ -it('testZeroScroll', function() { - var g = new Dygraph( - document.getElementById("graph"), - "X,Y\n" + - "1,0\n" + - "8,0\n" + - "9,0.1\n", - { - drawAxesAtZero: true, - animatedZooms: true, - avoidMinZero: true - }); -}); - /** * Verify scrolling all-zero region, new-style. */ diff --git a/bower.json b/bower.json deleted file mode 100644 index 6ebcc5cda..000000000 --- a/bower.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "dygraphs", - "main": "dist/dygraph.js", - "ignore": [ - "Makefile", - "NOTES", - "auto_tests", - "common", - "data.js", - "docs", - "experimental", - "file-size-stats.sh", - "gadget.xml", - "gallery", - "generate-combined.sh", - "generate-documentation.py", - "generate-download.py", - "generate-jar.sh", - "generate-jsdoc.sh", - "gwt", - "jsTestDriver.conf", - "jsdoc-toolkit", - "lint.sh", - "node_modules", - "package.json", - "phantom-driver.js", - "phantom-perf.js", - "push-to-web.sh", - "release.sh", - "releases.json", - "screenshot.png", - "scripts", - "test.sh", - "tests", - "thumbnail.png" - ] -} diff --git a/docs/header.html b/docs/header.html index 870c84c25..cc5881c49 100644 --- a/docs/header.html +++ b/docs/header.html @@ -6,9 +6,10 @@ + - + - + @@ -33,14 +33,12 @@ - diff --git a/tests/annotation-native.html b/tests/annotation-native.html index 4e4538d87..53ce249e3 100644 --- a/tests/annotation-native.html +++ b/tests/annotation-native.html @@ -1,7 +1,7 @@ - + Native format annotations diff --git a/tests/annotation.html b/tests/annotation.html index 002d4ddce..c180070ff 100644 --- a/tests/annotation.html +++ b/tests/annotation.html @@ -1,15 +1,8 @@ - + demo - - ", "
    ", "Zoom:", "hour ", @@ -14,7 +16,8 @@ Gallery.register( "full ", "Pan: ", "left ", - "right "].join("\n"); + "right ", + ""].join("\n"); }, run: function() { var r = [ ]; diff --git a/package.json b/package.json index ededf3f19..5eb7b2493 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dygraphs", - "version": "2.0.0-rc2", + "version": "2.0.0-rc3", "description": "dygraphs is a fast, flexible open source JavaScript charting library.", "main": "index.es5", "module": "index", diff --git a/tests/link-interaction.html b/tests/link-interaction.html index d2192fcfb..3a61efcea 100644 --- a/tests/link-interaction.html +++ b/tests/link-interaction.html @@ -4,7 +4,11 @@ noise - +
    From 87ba46ff9fb4ff7a160859bd0498844c179ce21a Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 28 Dec 2016 20:49:05 -0500 Subject: [PATCH 31/54] Rework the README a bit --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8e639e510..e539994d9 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,16 @@ The dygraphs JavaScript library produces interactive, zoomable charts of time se Learn more about it at [dygraphs.com](http://www.dygraphs.com). -Get help with dygraphs on -[Stack Overflow](http://stackoverflow.com/questions/tagged/dygraphs) (preferred) and -[Google Groups](http://groups.google.com/group/dygraphs-users) +Get help with dygraphs by browsing the on [Stack Overflow][] (preferred) and [Google Groups][]. ## Features * Plots time series without using an external server or Flash -* Supports [error bands](http://dygraphs.com/tests/legend-values.html) around data series -* Interactive [pan and zoom](http://dygraphs.com/tests/link-interaction.html) -* Displays values [on mouseover](http://dygraphs.com/tests/legend-values.html) -* Adjustable [averaging period](http://dygraphs.com/tests/temperature-sf-ny.html) -* Extensive set of [options](http://www.dygraphs.com/options.html) for customization. -* Compatible with the [Google Visualization API](http://dygraphs.com/data.html#datatable) +* Supports [error bands][] around data series +* Interactive [pan and zoom][] +* Displays values [on mouseover][] +* Adjustable [averaging period][] +* Extensive set of [options][] for customization. +* Compatible with the [Google Visualization API][gviz] ## Minimal Example ```html @@ -43,9 +41,27 @@ Get help with dygraphs on ``` -Learn more by reading [the tutorial](http://www.dygraphs.com/tutorial.html) and -seeing demonstrations of what dygraphs can do in the -[gallery](http://www.dygraphs.com/gallery). +Learn more by reading [the tutorial][] and seeing demonstrations of what +dygraphs can do in the [gallery][]. You can get `dygraph.js` and `dygraph.css` +from [cdnjs][] or [from NPM][npm] (see below). + +## Usage with a module loader + +Get dygraphs from NPM: + + npm install dygraphs + +You'll find pre-built JS & CSS files in `node_modules/dygraphs/dist`. If you're +using a module bundler like browserify or webpack, you can import dygraphs: + +```js +import Dygraph from 'dygraphs'; +// or: const Dygraph = require('dygraphs'); + +const g = new Dygraph('graphdiv', data, { /* options */ }); +``` + +Check out the [dygraphs-es6 repo][] for a fully-worked example. ## Development @@ -60,3 +76,17 @@ Read more about the dygraphs development process in the [developer guide](/DEVEL ## License(s) dygraphs is available under the MIT license, included in LICENSE.txt. + +[cdnjs]: https://cdnjs.com/libraries/dygraph +[the tutorial]: http://www.dygraphs.com/tutorial.html +[gallery]: http://www.dygraphs.com/gallery +[error bands]: http://dygraphs.com/tests/legend-values.html +[pan and zoom]: http://dygraphs.com/tests/link-interaction.html +[on mouseover]: http://dygraphs.com/tests/legend-values.html +[averaging period]: http://dygraphs.com/tests/temperature-sf-ny.html +[options]: http://www.dygraphs.com/options.html +[Stack Overflow]: http://stackoverflow.com/questions/tagged/dygraphs?sort=votes&pageSize=50 +[Google Groups]: http://groups.google.com/group/dygraphs-users +[gviz]: http://dygraphs.com/data.html#datatable +[npm]: https://www.npmjs.com/package/dygraphs +[dygraphs-es6 repo]: https://github.com/danvk/dygraphs-es6 From f808e16e56550f5260f4cf8c335424925e23e6b5 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Sun, 8 Jan 2017 12:13:28 -0500 Subject: [PATCH 32/54] revert change to demo.html from 1.1.1 --- tests/demo.html | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/demo.html b/tests/demo.html index 845e7eed7..83dff455e 100644 --- a/tests/demo.html +++ b/tests/demo.html @@ -46,7 +46,6 @@

    Demo

    xlabel: 'Date', ylabel: 'Count', axisLineColor: 'white', - showRangeSelector: true // drawXGrid: false } ); From 59ee387ba6d5113ceedba2b16b1c0c53ddfa072c Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 11 Jan 2017 11:13:03 -0500 Subject: [PATCH 33/54] Documentation updates --- docs/index.html | 2 +- src/dygraph.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.html b/docs/index.html index f96967218..aae433fb3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -53,7 +53,7 @@

    Features

  • Interactive out of the box: zoom, pan and mouseover are on by default.
  • Strong support for error bars / confidence intervals.
  • Highly customizable: using options and custom callbacks, you can make dygraphs do almost anything. -
  • dygraphs is highly compatible: it works in all major browsers (including IE8). You can even pinch to zoom on mobile/tablet devices! +
  • dygraphs is works in all recent browsers. You can even pinch to zoom on mobile/tablet devices!
  • There's an active community developing and supporting dygraphs.
  • diff --git a/src/dygraph.js b/src/dygraph.js index 8e6d6e04c..d5036690e 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -3010,6 +3010,7 @@ 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. + * @private */ Dygraph.prototype.cascadeDataDidUpdateEvent_ = function() { // TODO(danvk): there are some issues checking xAxisRange() and using @@ -3142,6 +3143,7 @@ Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { /** * Make a copy of input attributes, removing file as a convenience. + * @private */ Dygraph.copyUserAttrs_ = function(attrs) { var my_attrs = {}; From 0a31d41e94fae75808da6caa36e96fcdd40fd23f Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 11 Jan 2017 11:52:45 -0500 Subject: [PATCH 34/54] =?UTF-8?q?Bump=20to=20version=202=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5eb7b2493..b1ebdae04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dygraphs", - "version": "2.0.0-rc3", + "version": "2.0.0", "description": "dygraphs is a fast, flexible open source JavaScript charting library.", "main": "index.es5", "module": "index", From aa0b189f8cb22d64ce65cc9b205c90f6e4fd1257 Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Wed, 8 Feb 2017 13:20:36 -0500 Subject: [PATCH 35/54] Make dblclick event cancelable. (#840) Add demo of how to restore the dygraphs 1.x zoom out behavior. --- src/dygraph-interaction-model.js | 3 +- src/dygraph.js | 1 + tests/old-yrange-behavior.html | 64 ++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/old-yrange-behavior.html diff --git a/src/dygraph-interaction-model.js b/src/dygraph-interaction-model.js index 349fd3e57..494b63849 100644 --- a/src/dygraph-interaction-model.js +++ b/src/dygraph-interaction-model.js @@ -706,7 +706,8 @@ DygraphInteraction.defaultModel = { // Give plugins a chance to grab this event. var e = { canvasx: context.dragEndX, - canvasy: context.dragEndY + canvasy: context.dragEndY, + cancelable: true, }; if (g.cascadeEvents_('dblclick', e)) { return; diff --git a/src/dygraph.js b/src/dygraph.js index d5036690e..61e96f7f2 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -1350,6 +1350,7 @@ Dygraph.prototype.resetZoom = function() { const zoomCallback = this.getFunctionOption('zoomCallback'); // TODO(danvk): merge this block w/ the code below. + // TODO(danvk): factor out a generic, public zoomTo method. if (!animatedZooms) { this.dateWindow_ = null; this.axes_.forEach(axis => { diff --git a/tests/old-yrange-behavior.html b/tests/old-yrange-behavior.html new file mode 100644 index 000000000..d70ff1a5b --- /dev/null +++ b/tests/old-yrange-behavior.html @@ -0,0 +1,64 @@ + + + + + Old y-axis range behavior + + + + + +

    Old y-axis range behavior

    +

    In dygraphs 1.x, if you set a valueRange for the y-axis, zoomed in and then double-clicked to zoom out, then the chart would zoom out to the valueRange that you specified.

    +

    Starting with dygraphs 2, double-clicking will zoom out to the full range of the chart's data. This makes the x- and y-axes behave identically.

    +

    This demo shows you how to get the old behavior in dygraphs 2 using a plugin. View source to see how.

    + +
    +
    + + + + From c0e7b6254d879d6ccbfdd97b88eb904cc09cc9c1 Mon Sep 17 00:00:00 2001 From: klemens Date: Tue, 14 Feb 2017 22:17:25 +0100 Subject: [PATCH 36/54] spelling fixes --- docs/site.css | 2 +- docs/ssi_server.py | 2 +- gallery/number-format.js | 2 +- scripts/check-no-only.sh | 2 +- src/dygraph-options-reference.js | 2 +- src/dygraph-utils.js | 6 +++--- src/dygraph.js | 2 +- tests/number-format.html | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/site.css b/docs/site.css index 58232d73e..308ba7ad7 100644 --- a/docs/site.css +++ b/docs/site.css @@ -32,7 +32,7 @@ body { } } @media screen and (min-width: 768px) and (max-width: 992px) { - /* The topnav drops down to the next line between these sizes. We must accomodate. */ + /* The topnav drops down to the next line between these sizes. We must accommodate. */ body { padding-top: 130px; } diff --git a/docs/ssi_server.py b/docs/ssi_server.py index bf20b3837..d8386736e 100755 --- a/docs/ssi_server.py +++ b/docs/ssi_server.py @@ -9,7 +9,7 @@ -Run ./ssi_server.py in this directory and visit localhost:8000 for an exmaple. +Run ./ssi_server.py in this directory and visit localhost:8000 for an example. ''' import os diff --git a/gallery/number-format.js b/gallery/number-format.js index cc3d22fcb..e7d0d4039 100644 --- a/gallery/number-format.js +++ b/gallery/number-format.js @@ -5,7 +5,7 @@ Gallery.register( name: 'Number formatting', setup: function(parent) { parent.innerHTML = - "

    The default formatting mimicks printf with %.pg where p is" + + "

    The default formatting mimics printf with %.pg where p is" + " the precision to use. It turns out that JavaScript's toPrecision()" + " method is almost but not exactly equal to %g; they differ for values" + " with small absolute values (10^-1 to 10^-5 or so), with toPrecision()" + diff --git a/scripts/check-no-only.sh b/scripts/check-no-only.sh index 0977ec109..dc47eeb96 100755 --- a/scripts/check-no-only.sh +++ b/scripts/check-no-only.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Checks that no ".only" has made it into tests. This should never be commited, +# Checks that no ".only" has made it into tests. This should never be committed, # since it will disable the vast majority of tests. if grep -R '\.only(' auto_tests/tests; then diff --git a/src/dygraph-options-reference.js b/src/dygraph-options-reference.js index 4a066bb9f..3bf2a56a5 100644 --- a/src/dygraph-options-reference.js +++ b/src/dygraph-options-reference.js @@ -586,7 +586,7 @@ OPTIONS_REFERENCE = // "default": "null", "labels": ["Axis display", "Interactive Elements"], "type": "float", - "description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% pased the edges of the displayed values. null means no bounds." + "description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% passed the edges of the displayed values. null means no bounds." }, "title": { "labels": ["Chart labels"], diff --git a/src/dygraph-utils.js b/src/dygraph-utils.js index a9e4b221e..dabd4ea97 100644 --- a/src/dygraph-utils.js +++ b/src/dygraph-utils.js @@ -42,7 +42,7 @@ export var logRangeFraction = function(r0, r1, pct) { // Original calcuation: // pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0]))); // - // Multiply both sides by the right-side demoninator. + // Multiply both sides by the right-side denominator. // pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0]) // // add log(xRange[0]) to both sides @@ -265,7 +265,7 @@ export function isValidPoint(p, opt_allowNaNY) { }; /** - * Number formatting function which mimicks the behavior of %g in printf, i.e. + * Number formatting function which mimics the behavior of %g in printf, i.e. * either exponential or fixed format (without trailing 0s) is used depending on * the length of the generated string. The advantage of this format is that * there is a predictable upper bound on the resulting string length, @@ -377,7 +377,7 @@ export function hmsString_(hh, mm, ss, ms) { /** * Convert a JS date (millis since epoch) to a formatted string. * @param {number} time The JavaScript time value (ms since epoch) - * @param {boolean} utc Wether output UTC or local time + * @param {boolean} utc Whether output UTC or local time * @return {string} A date of one of these forms: * "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS" * @private diff --git a/src/dygraph.js b/src/dygraph.js index 61e96f7f2..ba4473925 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -3126,7 +3126,7 @@ Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) { 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. + // TODO(danvk): support cancellation of the update via this event. this.cascadeEvents_('dataWillUpdate', {}); this.file_ = file; diff --git a/tests/number-format.html b/tests/number-format.html index f85cf02b6..f722ff25e 100644 --- a/tests/number-format.html +++ b/tests/number-format.html @@ -7,7 +7,7 @@ -

    The default formatting mimicks printf with %.pg where p is +

    The default formatting mimics printf with %.pg where p is the precision to use. It turns out that JavaScript's toPrecision() method is almost but not exactly equal to %g; they differ for values with small absolute values (10^-1 to 10^-5 or so), with toPrecision() From f160e4ac8166f74d1f0e5604061564fbca5ba5a5 Mon Sep 17 00:00:00 2001 From: Drew Inglis Date: Tue, 2 May 2017 17:10:40 -0400 Subject: [PATCH 37/54] Fix two inconsistencies in dygraph-externs.js (#859) 1. The second argument of getOption should be marked as optional per jsdoc at: http://dygraphs.com/jsdoc/symbols/Dygraph.html#getOption 2. 'boolean' is typo'd as 'Boolean' in updateOptions. --- dygraph-externs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dygraph-externs.js b/dygraph-externs.js index 9cf956801..02330f8f5 100644 --- a/dygraph-externs.js +++ b/dygraph-externs.js @@ -40,7 +40,7 @@ Dygraph.prototype.isZoomed; /** @type {function(): string} */ Dygraph.prototype.toString; -/** @type {function(string, string)} */ +/** @type {function(string, string=)} */ Dygraph.prototype.getOption; /** @type {function(): number} */ @@ -127,7 +127,7 @@ Dygraph.prototype.isSeriesLocked; /** @type {function(): number} */ Dygraph.prototype.numAxes; -/** @type {function(Object, Boolean=)} */ +/** @type {function(Object, boolean=)} */ Dygraph.prototype.updateOptions; /** @type {function(number, number)} */ From 00eebc92ec7d1846599bf233dbc63b9ea3ac3095 Mon Sep 17 00:00:00 2001 From: Robert Konigsberg Date: Tue, 2 May 2017 17:11:44 -0400 Subject: [PATCH 38/54] Make setAnnotations' boolean parameter optional. (#851) --- dygraph-externs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dygraph-externs.js b/dygraph-externs.js index 02330f8f5..e8e2c4203 100644 --- a/dygraph-externs.js +++ b/dygraph-externs.js @@ -142,7 +142,7 @@ Dygraph.prototype.visibility; /** @type {function(number, boolean)} */ Dygraph.prototype.setVisibility; -/** @type {function(Array., boolean)} */ +/** @type {function(Array., boolean=)} */ Dygraph.prototype.setAnnotations; /** @type {function(): Array.} */ From f6e73ea983b61b50a6152c98a9945725eb45edb2 Mon Sep 17 00:00:00 2001 From: Madis Allikmaa Date: Mon, 8 May 2017 17:04:32 +0300 Subject: [PATCH 39/54] Fix gallery navigation from interaction demo (#825) --- gallery/interaction.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gallery/interaction.js b/gallery/interaction.js index a90373754..9dce5b7ae 100644 --- a/gallery/interaction.js +++ b/gallery/interaction.js @@ -49,9 +49,6 @@ Gallery.register( }, run: function() { - var lastClickedGraph; - document.addEventListener("mousewheel", function() { lastClickedGraph = null; }); - document.addEventListener("click", function() { lastClickedGraph = null; }); new Dygraph(document.getElementById("div_g"), NoisyData, { errorBars : true }); new Dygraph(document.getElementById("div_g2"), @@ -84,9 +81,5 @@ Gallery.register( }, underlayCallback : captureCanvas }); - }, - clean: function() { - document.removeEventListener('mousewheel'); - document.removeEventListener('click'); } }); From 64f1c4dfd7425931fcd1bd9949157c0ba6958656 Mon Sep 17 00:00:00 2001 From: Jeff VanDyke Date: Wed, 20 Sep 2017 18:17:03 -0400 Subject: [PATCH 40/54] Added pixelRatio option to override canvas upscaling. Resolves #876, test included. (#877) * Added pixelRatio option, using where appropriate. Falls back to old behavior if not specified. Added to options reference, Added to Dygraph.prototype.resizeElements_, Added to rangeSelector.prototype.updateVisibility. * Fixed bug in range-selector pixelRatio implementation, tests pass * added test for the pixelRatio option, properly run. First fails without change, then passes after change. * Added pull request suggestions Fix typo in docs, documented a float type, Simplified method of reading option. * Added note about pixelRatio affecting resolution --- auto_tests/tests/hidpi.js | 31 +++++++++++++++++++++++++++++++ src/dygraph-options-reference.js | 6 ++++++ src/dygraph.js | 6 ++++-- src/plugins/range-selector.js | 9 +++++---- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/auto_tests/tests/hidpi.js b/auto_tests/tests/hidpi.js index 1dd131c7b..ceb3a49dc 100644 --- a/auto_tests/tests/hidpi.js +++ b/auto_tests/tests/hidpi.js @@ -45,5 +45,36 @@ it('testDoesntCreateScrollbars', function() { assert.equal(sw, document.body.scrollWidth); }); +it('should be influenced by options.pixelRatio', function () { + var graph = document.getElementById("graph"); + + // make sure devicePixelRatio is still setup to not 1. + assert(devicePixelRatio > 1.5, 'devicePixelRatio is not much greater than 1.'); + + var data = "X,Y\n" + + "0,-1\n" + + "1,0\n" + + "2,1\n" + + "3,0\n"; + + // first try a default one + var g1 = new Dygraph(graph, data, {}); + var area1 = g1.getArea(); + + var g2 = new Dygraph(graph, data, { pixelRatio: 1 }); + var area2 = g2.getArea(); + + var g3 = new Dygraph(graph, data, { pixelRatio: 3 }); + var area3 = g3.getArea(); + + assert.deepEqual(area1, area2, 'areas 1 and 2 are not the same'); + assert.deepEqual(area2, area3, 'areas 2 and 3 are not the same'); + + assert.notEqual(g1.canvas_.width, g2.canvas_.width, + 'Expected, for devicePixelRatio != 1, ' + + 'that setting options.pixelRatio would change the canvas width'); + assert.equal(g2.canvas_.width * 3, g3.canvas_.width, + 'Expected that pixelRatio of 3 vs 1 would triple the canvas width.'); +}); }); diff --git a/src/dygraph-options-reference.js b/src/dygraph-options-reference.js index 3bf2a56a5..9cffd5e60 100644 --- a/src/dygraph-options-reference.js +++ b/src/dygraph-options-reference.js @@ -299,6 +299,12 @@ OPTIONS_REFERENCE = // "type": "integer", "description": "Width, in pixels, of the chart. If the container div has been explicitly sized, this will be ignored." }, + "pixelRatio": { + "default": "(devicePixelRatio / context.backingStoreRatio)", + "labels": ["Overall display"], + "type": "float", + "description": "Overrides the pixel ratio scaling factor for the canvas's 2d context. Ordinarily, this is set to the devicePixelRatio / (context.backingStoreRatio || 1), so on mobile devices, where the devicePixelRatio can be somewhere around 3, performance can be improved by overriding this value to something less precise, like 1, at the expense of resolution." + }, "interactionModel": { "default": "...", "labels": ["Interactive Elements"], diff --git a/src/dygraph.js b/src/dygraph.js index ba4473925..531191fa8 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -861,7 +861,9 @@ Dygraph.prototype.resizeElements_ = function() { this.graphDiv.style.width = this.width_ + "px"; this.graphDiv.style.height = this.height_ + "px"; - var canvasScale = utils.getContextPixelRatio(this.canvas_ctx_); + var pixelRatioOption = this.getNumericOption('pixelRatio') + + var canvasScale = pixelRatioOption || utils.getContextPixelRatio(this.canvas_ctx_); this.canvas_.width = this.width_ * canvasScale; this.canvas_.height = this.height_ * canvasScale; this.canvas_.style.width = this.width_ + "px"; // for IE @@ -870,7 +872,7 @@ Dygraph.prototype.resizeElements_ = function() { this.canvas_ctx_.scale(canvasScale, canvasScale); } - var hiddenScale = utils.getContextPixelRatio(this.hidden_ctx_); + var hiddenScale = pixelRatioOption || utils.getContextPixelRatio(this.hidden_ctx_); this.hidden_.width = this.width_ * hiddenScale; this.hidden_.height = this.height_ * hiddenScale; this.hidden_.style.width = this.width_ + "px"; // for IE diff --git a/src/plugins/range-selector.js b/src/plugins/range-selector.js index 7f91dc80c..c1f70f965 100644 --- a/src/plugins/range-selector.js +++ b/src/plugins/range-selector.js @@ -161,8 +161,8 @@ rangeSelector.prototype.updateVisibility_ = function() { * Resizes the range selector. */ rangeSelector.prototype.resize_ = function() { - function setElementRect(canvas, context, rect) { - var canvasScale = utils.getContextPixelRatio(context); + function setElementRect(canvas, context, rect, pixelRatioOption) { + var canvasScale = pixelRatioOption || utils.getContextPixelRatio(context); canvas.style.top = rect.y + 'px'; canvas.style.left = rect.x + 'px'; @@ -189,8 +189,9 @@ rangeSelector.prototype.resize_ = function() { h: this.getOption_('rangeSelectorHeight') }; - setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_); - setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_); + var pixelRatioOption = this.dygraph_.getNumericOption('pixelRatio'); + setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_, pixelRatioOption); + setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_, pixelRatioOption); }; /** From c33b49f95618b6c5891dbef82ee76ea69ce3c783 Mon Sep 17 00:00:00 2001 From: lukevmorris Date: Thu, 7 Dec 2017 14:30:11 -0800 Subject: [PATCH 41/54] Millisecond granularity (#893) * Add milliseconds granularity wtih changes from #777 with suggestions taken into account and mergeable with master. * Fix granularities according to original PR. * Add assertions for millisecond granularities * Add an example for labels below SECONDLY granularity --- auto_tests/tests/date_ticker.js | 13 +++++++ src/dygraph-tickers.js | 60 ++++++++++++++++++++------------- src/dygraph-utils.js | 6 ++++ 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/auto_tests/tests/date_ticker.js b/auto_tests/tests/date_ticker.js index c02331dc7..fc18733ed 100644 --- a/auto_tests/tests/date_ticker.js +++ b/auto_tests/tests/date_ticker.js @@ -263,6 +263,19 @@ it('testAllDateTickers', function() { assert.deepEqual([{"v":1307908020000,"label":"19:47"},{"v":1307908050000,"label":"19:47:30"},{"v":1307908080000,"label":"19:48"},{"v":1307908110000,"label":"19:48:30"},{"v":1307908140000,"label":"19:49"},{"v":1307908170000,"label":"19:49:30"}], ticker(1307908000112, 1307908172259, 800, options)); assert.deepEqual([{"v":1307908020000,"label":"19:47"},{"v":1307908050000,"label":"19:47:30"},{"v":1307908080000,"label":"19:48"},{"v":1307908110000,"label":"19:48:30"},{"v":1307908140000,"label":"19:49"},{"v":1307908170000,"label":"19:49:30"}], ticker(1307908000112, 1307908173260, 800, options)); assert.deepEqual([{"v":978307200000,"label":"Jan 2001"},{"v":986083200000,"label":"Apr 2001"},{"v":993945600000,"label":"Jul 2001"},{"v":1001894400000,"label":"Oct 2001"}], ticker(978307200000, 1001894400000, 400, options)); + + assert.deepEqual([{"v":1307908000110,"label":"40.110"},{"v":1307908000111,"label":"40.111"},{"v":1307908000112,"label":"40.112"},{"v":1307908000113,"label":"40.113"}], ticker(1307908000110, 1307908000113, 200, options)); + assert.deepEqual([{"v":1307908000110,"label":"40.110"},{"v":1307908000112,"label":"40.112"},{"v":1307908000114,"label":"40.114"},{"v":1307908000116,"label":"40.116"}], ticker(1307908000110, 1307908000116, 200, options)); + assert.deepEqual([{"v":1307908000110,"label":"40.110"},{"v":1307908000115,"label":"40.115"},{"v":1307908000120,"label":"40.120"},{"v":1307908000125,"label":"40.125"}], ticker(1307908000110, 1307908000125, 200, options)); + assert.deepEqual([{"v":1307908000110,"label":"40.110"},{"v":1307908000120,"label":"40.120"},{"v":1307908000130,"label":"40.130"},{"v":1307908000140,"label":"40.140"}], ticker(1307908000110, 1307908000140, 200, options)); + + assert.deepEqual([{"v":1307908000100,"label":"40.100"},{"v":1307908000150,"label":"40.150"},{"v":1307908000200,"label":"40.200"},{"v":1307908000250,"label":"40.250"}], ticker(1307908000100, 1307908000250, 200, options)); + assert.deepEqual([{"v":1307908000100,"label":"40.100"},{"v":1307908000150,"label":"40.150"},{"v":1307908000200,"label":"40.200"},{"v":1307908000250,"label":"40.250"}], ticker(1307908000090, 1307908000260, 200, options)); + + assert.deepEqual([{"v":1307908000100,"label":"40.100"},{"v":1307908000200,"label":"40.200"},{"v":1307908000300,"label":"40.300"},{"v":1307908000400,"label":"40.400"}], ticker(1307908000100, 1307908000400, 200, options)); + assert.deepEqual([{"v":1307908000100,"label":"40.100"},{"v":1307908000200,"label":"40.200"},{"v":1307908000300,"label":"40.300"},{"v":1307908000400,"label":"40.400"}], ticker(1307908000100, 1307908000410, 200, options)); + + assert.deepEqual([{"v":1307908000000,"label":"40.000"},{"v":1307908000500,"label":"40.500"},{"v":1307908001000,"label":"41.000"},{"v":1307908001500,"label":"41.500"}], ticker(1307908000000, 1307908001500, 200, options)); }); }); diff --git a/src/dygraph-tickers.js b/src/dygraph-tickers.js index f152bf996..13cc74514 100644 --- a/src/dygraph-tickers.js +++ b/src/dygraph-tickers.js @@ -220,29 +220,36 @@ export var dateTicker = function(a, b, pixels, opts, dygraph, vals) { // Time granularity enumeration export var Granularity = { - SECONDLY: 0, - TWO_SECONDLY: 1, - FIVE_SECONDLY: 2, - TEN_SECONDLY: 3, - THIRTY_SECONDLY : 4, - MINUTELY: 5, - TWO_MINUTELY: 6, - FIVE_MINUTELY: 7, - TEN_MINUTELY: 8, - THIRTY_MINUTELY: 9, - HOURLY: 10, - TWO_HOURLY: 11, - SIX_HOURLY: 12, - DAILY: 13, - TWO_DAILY: 14, - WEEKLY: 15, - MONTHLY: 16, - QUARTERLY: 17, - BIANNUAL: 18, - ANNUAL: 19, - DECADAL: 20, - CENTENNIAL: 21, - NUM_GRANULARITIES: 22 + MILLISECONDLY: 0, + TWO_MILLISECONDLY: 1, + FIVE_MILLISECONDLY: 2, + TEN_MILLISECONDLY: 3, + FIFTY_MILLISECONDLY: 4, + HUNDRED_MILLISECONDLY: 5, + FIVE_HUNDRED_MILLISECONDLY: 6, + SECONDLY: 7, + TWO_SECONDLY: 8, + FIVE_SECONDLY: 9, + TEN_SECONDLY: 10, + THIRTY_SECONDLY: 11, + MINUTELY: 12, + TWO_MINUTELY: 13, + FIVE_MINUTELY: 14, + TEN_MINUTELY: 15, + THIRTY_MINUTELY: 16, + HOURLY: 17, + TWO_HOURLY: 18, + SIX_HOURLY: 19, + DAILY: 20, + TWO_DAILY: 21, + WEEKLY: 22, + MONTHLY: 23, + QUARTERLY: 24, + BIANNUAL: 25, + ANNUAL: 26, + DECADAL: 27, + CENTENNIAL: 28, + NUM_GRANULARITIES: 29 } // Date components enumeration (in the order of the arguments in Date) @@ -273,6 +280,13 @@ var DateField = { * @type {Array.<{datefield:number, step:number, spacing:number}>} */ var TICK_PLACEMENT = []; +TICK_PLACEMENT[Granularity.MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 1, spacing: 1}; +TICK_PLACEMENT[Granularity.TWO_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 2, spacing: 2}; +TICK_PLACEMENT[Granularity.FIVE_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 5, spacing: 5}; +TICK_PLACEMENT[Granularity.TEN_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 10, spacing: 10}; +TICK_PLACEMENT[Granularity.FIFTY_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 50, spacing: 50}; +TICK_PLACEMENT[Granularity.HUNDRED_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 100, spacing: 100}; +TICK_PLACEMENT[Granularity.FIVE_HUNDRED_MILLISECONDLY] = {datefield: DateField.DATEFIELD_MS, step: 500, spacing: 500}; TICK_PLACEMENT[Granularity.SECONDLY] = {datefield: DateField.DATEFIELD_SS, step: 1, spacing: 1000 * 1}; TICK_PLACEMENT[Granularity.TWO_SECONDLY] = {datefield: DateField.DATEFIELD_SS, step: 2, spacing: 1000 * 2}; TICK_PLACEMENT[Granularity.FIVE_SECONDLY] = {datefield: DateField.DATEFIELD_SS, step: 5, spacing: 1000 * 5}; diff --git a/src/dygraph-utils.js b/src/dygraph-utils.js index dabd4ea97..c0b8f34b6 100644 --- a/src/dygraph-utils.js +++ b/src/dygraph-utils.js @@ -1214,6 +1214,12 @@ export function dateAxisLabelFormatter(date, granularity, opts) { if (frac === 0 || granularity >= DygraphTickers.Granularity.DAILY) { // e.g. '21 Jan' (%d%b) return zeropad(day) + ' ' + SHORT_MONTH_NAMES_[month]; + } else if (granularity < DygraphTickers.Granularity.SECONDLY) { + // e.g. 40.310 (meaning 40 seconds and 310 milliseconds) + var str = "" + millis; + return zeropad(secs) + "." + ('000'+str).substring(str.length); + } else if (granularity > DygraphTickers.Granularity.MINUTELY) { + return hmsString_(hours, mins, secs, 0); } else { return hmsString_(hours, mins, secs, millis); } From f598f5e131cf7644fa168bfe49bded499d16363f Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Thu, 7 Dec 2017 14:59:05 -0800 Subject: [PATCH 42/54] Bump version to 2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1ebdae04..21d4c60eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dygraphs", - "version": "2.0.0", + "version": "2.0.1", "description": "dygraphs is a fast, flexible open source JavaScript charting library.", "main": "index.es5", "module": "index", From 8dc4700ae339d19b74e592ef91f0da3092f98438 Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Fri, 8 Dec 2017 14:19:21 -0800 Subject: [PATCH 43/54] Bump version to 2.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21d4c60eb..70fbc897e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dygraphs", - "version": "2.0.1", + "version": "2.1.0", "description": "dygraphs is a fast, flexible open source JavaScript charting library.", "main": "index.es5", "module": "index", From cc2bca6914b953332fe51a93f9be6d172871f4e6 Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Tue, 12 Dec 2017 10:46:32 -0800 Subject: [PATCH 44/54] Remove release.sh, which is now out of date --- scripts/release.sh | 70 ---------------------------------------------- 1 file changed, 70 deletions(-) delete mode 100755 scripts/release.sh diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 34a0fd1ae..000000000 --- a/scripts/release.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -# This script "releases" a version of dygraphs. - -if [ $# -ne 1 ]; then - echo "Usage: $0 X.Y.Z" >&2 - exit 1 -fi - -VERSION=$1 -echo $VERSION | egrep '\d+\.\d+\.\d+' > /dev/null -if [ $? -ne 0 ]; then - echo "Version must be of the form 1.2.3 (got '$VERSION')" >&2 - exit 1 -fi - -# Make sure this is being run from a release branch with the correct name. -branch=$(git rev-parse --abbrev-ref HEAD) -if [ $branch != "release-$VERSION" ]; then - echo "Must be on a branch named 'release-$VERSION' (found '$branch')" >&2 - exit 1 -fi - -git status | grep 'working directory clean' > /dev/null -if [ $? -ne 0 ]; then - echo "Must release with a clean working directory. Commit your changes." >&2 - exit 1 -fi - -grep "$VERSION" package.json -if [ $? -ne 0 ]; then - echo "Version in package.json doesn't match command line argument." >&2 - exit 1 -fi - -grep "$VERSION" releases.json -if [ $? -ne 0 ]; then - echo "Version $VERSION does not appear in releases.json." >&2 - exit 1 -fi - -set -o errexit -npm run build -npm run test -set +o errexit - -# Push a permanent copy of documentation & generated files to a versioned copy -# of the site. This is where the downloadable files are generated. -# TODO(danvk): make sure this actually generates the downloadable files! -echo "Pushing docs and generated files to dygraphs.com/$VERSION" -./push-to-web.sh dygraphs.com:dygraphs.com/$VERSION -if [ $? -ne 0 ]; then - echo "Push to web failed" >&2 - exit 1 -fi - -set -o errexit - -COMMIT=$(git rev-parse HEAD) -echo "Tagging commit $COMMIT as version $VERSION" -git tag -a "v$VERSION" -m "Release of version $VERSION" -git push --tags - -echo "Release was successful!" -echo "Pushing the new version to dygraphs.com..." -./push-to-web.sh dygraphs.com:dygraphs.com - -echo "Success!\n" - -# Discourage users from working on the "releases" branch. -git checkout master From ac422b3aa23612c220b14e938fbae79d01b40b86 Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Tue, 12 Dec 2017 14:26:57 -0800 Subject: [PATCH 45/54] Bump versions and add release notes --- docs/versions.html | 104 ++++++++++++++++++++++++++++++++++++++++----- releases.json | 8 ++++ src/dygraph.js | 2 +- 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/docs/versions.html b/docs/versions.html index a5974b56f..ef0491d63 100644 --- a/docs/versions.html +++ b/docs/versions.html @@ -27,6 +27,89 @@

    Version History

    For links to download each release, see the Downloads page.

    + + + + + + + + - + +
    2.1.0

    2017-12-08

    + New features: +
      +
    • Double click event can be captured and cancelled by plugins
    • +
    • setAnnotations's second parameter is now an optional boolean
    • +
    • Add `pixelRatio` option, which may allow improved performance on smaller screens by controlling the canvas' pixel ratio
    • +
    • X-axis label and tick logic can now operate at millisecond-level granularity
    • +
    + + Bug fixes: +
      +
    • Repair a bug in "Custom interaction modals" demo
    • +
    + + Internal refactors/fixes: +
      +
    • Fix various spelling mistakes
    • +
    • Fix a couple of type signatures in dygraph-externs.js
    • +
    +
    2.0.0

    2017-01-11

    + Breaking changes: +
      +
    • JS files were renamed to dygraph.js and dygraph.min.js.
    • +
    • There's now a dygraph.css file that you must include.
    • +
    • Dropped support for OldIE and other non-standard browsers. dygraphs works in IE11. I'm not sure about IE9 and IE10.
    • +
    • Double-click to unzoom zooms all the way out (and ignores valueRange).
    • +
    • Dropped old-style per-axis/per-series options.
    • +
    + + New features: +
      +
    • Add a legendFormatter option
    • +
    • `this` is the Dygraph object in all callbacks
    • +
    • pass through (row, col) to valueFormatter
    • +
    • Option to not sync range in extras/synchronizer.js
    • +
    • Additional options for styling the range selector
    • +
    • getRowForX method
    • +
    • setVisibility can set the visibility of multiple series at once.
    • +
    • crosshair plugin extra
    • +
    • rebase/straw broom plugin
    • +
    • highlightSeriesBackgroundColor option
    • +
    • yAxisExtremes() method.
    • +
    • Passing strings in native format now throws. (Previously it kinda sorta worked.)
    • +
    + + Bug fixes: +
      +
    • Selections are always cleared with animations
    • +
    • synchronizer calls previously-set callbacks
    • +
    • synchronizer only syncs when graphs are ready
    • +
    • Reset on synchronized graphs failed
    • +
    • fix to improve synchronizer performance
    • +
    • binary search bug fix in synchronizer
    • +
    • Fix range selection when chart is located inside fullscreen element
    • +
    • fillAlpha can be set per-series when fillGraph is set.
    • +
    • xRangePad was ignored on unzoom
    • +
    • Allow selected points where canvas-y coordinate is 0
    • +
    • Using valueRange with Logscale and yRangePad has unexpected results
    • +
    • With "drawGapEdgePoints", unwanted point often drawn at beginning of chart
    • +
    + + Other user-visible changes: +
      +
    • “legend: follow” positioning changes
    • +
    + + Internal refactors: +
      +
    • Code moved into a “src/“ directory
    • +
    • Tests use Mocha instead of jstd
    • +
    • dygraphs is split into ES6 modules and uses some ES6 features (e.g. arrows and destructuring).
    • +
    • dygraphs is built using babel & browserify
    • +
    • Code coverage is tracked continuously
    • +
    • Bundle size is now tracked continuously
    • +
    +
    1.1.1

    2015-06-01

    @@ -35,20 +118,21 @@

    Version History

  • Minor bug fixes.
  • 1.1.0

    2014-12-03

    Highlights include:
      -
    • dygraphs is now "retina" compatible. -
    • Dramatically improved performance for filled charts (i.e. fillGraph) -
    • More sensible date ticks: "Jan 08"→"Jan 2008", "29Jan"→"29 Jan" -
    • Using a non-existent option now throws (w/ dygraph-combined-dev.js) -
    • x-axis log scales -
    • The labelsUTC option forces UTC formatting for all labels. -
    • The new DataHandler system allows for more flexibility in data loading. -
    • "this" is set to the dygraph in all callbacks. -
    • dygraphs has shrunk, because we moved some stuff into "extras" (133kb→122kb) +
    • dygraphs is now "retina" compatible.
    • +
    • Dramatically improved performance for filled charts (i.e. fillGraph)
    • +
    • More sensible date ticks: "Jan 08"→"Jan 2008", "29Jan"→"29 Jan"
    • +
    • Using a non-existent option now throws (w/ dygraph-combined-dev.js)
    • +
    • x-axis log scales
    • +
    • The labelsUTC option forces UTC formatting for all labels.
    • +
    • The new DataHandler system allows for more flexibility in data loading.
    • +
    • "this" is set to the dygraph in all callbacks.
    • +
    • dygraphs has shrunk, because we moved some stuff into "extras" (133kb→122kb)
    This will be the last major release to support browsers without a native <canvas> implementation. See blog post for more details. diff --git a/releases.json b/releases.json index 24496bf6e..4f567e684 100644 --- a/releases.json +++ b/releases.json @@ -1,4 +1,12 @@ [ + { + "version": "2.1.0", + "files": [ + "dygraph.min.js", + "dygraph.js", + "dygraph.css" + ] + }, { "version": "2.0.0", "files": [ diff --git a/src/dygraph.js b/src/dygraph.js index 531191fa8..1de4485d5 100644 --- a/src/dygraph.js +++ b/src/dygraph.js @@ -89,7 +89,7 @@ var Dygraph = function(div, data, opts) { }; Dygraph.NAME = "Dygraph"; -Dygraph.VERSION = "2.0.0"; +Dygraph.VERSION = "2.1.0"; // Various default values Dygraph.DEFAULT_ROLL_PERIOD = 1; From 61767ef761b66b06e089cd081ac68527575af38b Mon Sep 17 00:00:00 2001 From: John Fremlin Date: Sun, 31 Dec 2017 13:32:36 -0500 Subject: [PATCH 46/54] Make sure that canvasx and canvasy properties are initialized from the start (#896) Adding fields to a structure after it is created can be slow on some browsers, like Chrome. Adding a demo to benchmark many points, this seems to speed up my Chromium from about 2.8-3s to about 1.8s. Thanks to Christopher Palmer (@thecav) for the analysis and specific suggestion. --- gallery/data.js | 8 ++++++++ gallery/index.html | 1 + gallery/many-points.js | 17 +++++++++++++++++ src/datahandler/datahandler.js | 4 +++- 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 gallery/many-points.js diff --git a/gallery/data.js b/gallery/data.js index bbccab052..3ab0b66bb 100644 --- a/gallery/data.js +++ b/gallery/data.js @@ -2683,3 +2683,11 @@ var stockData = function() { "2009-09-15,9280.67;9712.28;9829.87,4297.2232125907;4497.07133894216;4551.51896800004\n" + "2009-10-15,9487.67;9712.73;10092.2,4388.84340147194;4492.9525342659;4668.48924723722\n"; }; + +function dataManyPoints() { + var data = []; + for (var i = 0; i < 1000000; ++i) { + data[i] = [i, i % 1009, i % 1013, i % 1019, i % 1021] + } + return data +} diff --git a/gallery/index.html b/gallery/index.html index 6d546b0a0..c834c318a 100644 --- a/gallery/index.html +++ b/gallery/index.html @@ -33,6 +33,7 @@ +