From 763f71df156ed1bb0708129c1c42deb134b94a79 Mon Sep 17 00:00:00 2001 From: Brandon Luong Date: Fri, 15 Aug 2014 13:03:51 -0700 Subject: [PATCH 1/5] 831 - Width and height account for gutter Close #831. --- plottable.d.ts | 3 --- plottable.js | 4 ++-- src/components/categoryAxis.ts | 4 ++-- test/components/categoryAxisTests.ts | 12 ++++++++++++ test/tests.js | 11 +++++++++++ 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index ded5491848..5edacf4790 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -843,9 +843,6 @@ declare module Plottable { declare module Plottable { module Abstract { class NewStyleBarPlot extends NewStylePlot { - static _barAlignmentToFactor: { - [x: string]: number; - }; static DEFAULT_WIDTH: number; constructor(xScale: Scale, yScale: Scale); baseline(value: number): any; diff --git a/plottable.js b/plottable.js index b9decd5ced..97ee9bba4f 100644 --- a/plottable.js +++ b/plottable.js @@ -3961,8 +3961,8 @@ var Plottable; this.measurer = new Plottable.Util.Text.CachingCharacterMeasurer(this._tickLabelContainer.append("text")); }; Category.prototype._requestedSpace = function (offeredWidth, offeredHeight) { - var widthRequiredByTicks = this._isHorizontal() ? 0 : this._maxLabelTickLength() + this.tickLabelPadding(); - var heightRequiredByTicks = this._isHorizontal() ? this._maxLabelTickLength() + this.tickLabelPadding() : 0; + var widthRequiredByTicks = this._isHorizontal() ? 0 : this._maxLabelTickLength() + this.tickLabelPadding() + this.gutter(); + var heightRequiredByTicks = this._isHorizontal() ? this._maxLabelTickLength() + this.tickLabelPadding() + this.gutter() : 0; if (this._scale.domain().length === 0) { return { width: 0, height: 0, wantsWidth: false, wantsHeight: false }; } diff --git a/src/components/categoryAxis.ts b/src/components/categoryAxis.ts index 8552bfcd63..a7d7356117 100644 --- a/src/components/categoryAxis.ts +++ b/src/components/categoryAxis.ts @@ -32,8 +32,8 @@ export module Axis { } public _requestedSpace(offeredWidth: number, offeredHeight: number): ISpaceRequest { - var widthRequiredByTicks = this._isHorizontal() ? 0 : this._maxLabelTickLength() + this.tickLabelPadding(); - var heightRequiredByTicks = this._isHorizontal() ? this._maxLabelTickLength() + this.tickLabelPadding() : 0; + var widthRequiredByTicks = this._isHorizontal() ? 0 : this._maxLabelTickLength() + this.tickLabelPadding() + this.gutter(); + var heightRequiredByTicks = this._isHorizontal() ? this._maxLabelTickLength() + this.tickLabelPadding() + this.gutter() : 0; if (this._scale.domain().length === 0) { return {width: 0, height: 0, wantsWidth: false, wantsHeight: false }; diff --git a/test/components/categoryAxisTests.ts b/test/components/categoryAxisTests.ts index 3806026ff3..4d948f1857 100644 --- a/test/components/categoryAxisTests.ts +++ b/test/components/categoryAxisTests.ts @@ -25,4 +25,16 @@ describe("Category Axes", () => { assert.isFalse(s.wantsHeight, "it doesn't want height"); svg.remove(); }); + + it("width and height account for gutter. ticklength, and padding", () => { + var svg = generateSVG(400, 400); + var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); + var ca = new Plottable.Axis.Category(xScale, "left"); + var ca2 = new Plottable.Axis.Category(xScale, "bottom"); + ca.renderTo(svg); + ca2.renderTo(svg); + assert.operator(ca.width(), ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + assert.operator(ca2.height(), ">", ca2.tickLabelPadding() + ca2.gutter() + ca2.tickLength()); + svg.remove(); + }); }); diff --git a/test/tests.js b/test/tests.js index bf02ef615d..ec467fd3d1 100644 --- a/test/tests.js +++ b/test/tests.js @@ -637,6 +637,17 @@ describe("Category Axes", function () { assert.isFalse(s.wantsHeight, "it doesn't want height"); svg.remove(); }); + it("width and height account for gutter. ticklength, and padding", function () { + var svg = generateSVG(400, 400); + var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); + var ca = new Plottable.Axis.Category(xScale, "left"); + var ca2 = new Plottable.Axis.Category(xScale, "bottom"); + ca.renderTo(svg); + ca2.renderTo(svg); + assert.operator(ca.width(), ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + assert.operator(ca2.height(), ">", ca2.tickLabelPadding() + ca2.gutter() + ca2.tickLength()); + svg.remove(); + }); }); var assert = chai.assert; From 469fa88995f5904d87591c7e926d74f6df1ec543 Mon Sep 17 00:00:00 2001 From: Brandon Luong Date: Fri, 15 Aug 2014 14:51:43 -0700 Subject: [PATCH 2/5] More accurate testing --- test/components/categoryAxisTests.ts | 42 ++++++++++++++++++++++++---- test/tests.js | 33 ++++++++++++++++++---- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/test/components/categoryAxisTests.ts b/test/components/categoryAxisTests.ts index 4d948f1857..55c64e9762 100644 --- a/test/components/categoryAxisTests.ts +++ b/test/components/categoryAxisTests.ts @@ -26,15 +26,47 @@ describe("Category Axes", () => { svg.remove(); }); - it("width and height account for gutter. ticklength, and padding", () => { + it("width and height account for gutter. ticklength, and padding on vertical axes", () => { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "left"); - var ca2 = new Plottable.Axis.Category(xScale, "bottom"); ca.renderTo(svg); - ca2.renderTo(svg); - assert.operator(ca.width(), ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); - assert.operator(ca2.height(), ">", ca2.tickLabelPadding() + ca2.gutter() + ca2.tickLength()); + + var axisWidth = ca.width(); + assert.operator(axisWidth, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + ca.tickLabelPadding(ca.tickLabelPadding() + 5); + assert.operator(ca.width(), ">", axisWidth); + + axisWidth = ca.width(); + ca.gutter(ca.gutter() + 5); + assert.operator(ca.width(), ">", axisWidth); + + axisWidth = ca.width(); + ca.tickLength(ca.tickLength() + 5); + assert.operator(ca.width(), ">", axisWidth); + + svg.remove(); + }); + + it("width and height account for gutter. ticklength, and padding on horizontal axes", () => { + var svg = generateSVG(400, 400); + var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); + var ca = new Plottable.Axis.Category(xScale, "bottom"); + ca.renderTo(svg); + + var axisHeight = ca.height(); + assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + ca.tickLabelPadding(ca.tickLabelPadding() + 5); + assert.operator(ca.height(), ">", axisHeight); + + axisHeight = ca.height(); + ca.gutter(ca.gutter() + 5); + assert.operator(ca.width(), ">", axisHeight); + + axisHeight = ca.height(); + ca.tickLength(ca.tickLength() + 5); + assert.operator(ca.height(), ">", axisHeight); + svg.remove(); }); }); diff --git a/test/tests.js b/test/tests.js index ec467fd3d1..1861fb537e 100644 --- a/test/tests.js +++ b/test/tests.js @@ -637,15 +637,38 @@ describe("Category Axes", function () { assert.isFalse(s.wantsHeight, "it doesn't want height"); svg.remove(); }); - it("width and height account for gutter. ticklength, and padding", function () { + it("width and height account for gutter. ticklength, and padding on vertical axes", function () { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "left"); - var ca2 = new Plottable.Axis.Category(xScale, "bottom"); ca.renderTo(svg); - ca2.renderTo(svg); - assert.operator(ca.width(), ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); - assert.operator(ca2.height(), ">", ca2.tickLabelPadding() + ca2.gutter() + ca2.tickLength()); + var axisWidth = ca.width(); + assert.operator(axisWidth, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + ca.tickLabelPadding(ca.tickLabelPadding() + 5); + assert.operator(ca.width(), ">", axisWidth); + axisWidth = ca.width(); + ca.gutter(ca.gutter() + 5); + assert.operator(ca.width(), ">", axisWidth); + axisWidth = ca.width(); + ca.tickLength(ca.tickLength() + 5); + assert.operator(ca.width(), ">", axisWidth); + svg.remove(); + }); + it("width and height account for gutter. ticklength, and padding on horizontal axes", function () { + var svg = generateSVG(400, 400); + var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); + var ca = new Plottable.Axis.Category(xScale, "bottom"); + ca.renderTo(svg); + var axisHeight = ca.height(); + assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); + ca.tickLabelPadding(ca.tickLabelPadding() + 5); + assert.operator(ca.height(), ">", axisHeight); + axisHeight = ca.height(); + ca.gutter(ca.gutter() + 5); + assert.operator(ca.width(), ">", axisHeight); + axisHeight = ca.height(); + ca.tickLength(ca.tickLength() + 5); + assert.operator(ca.height(), ">", axisHeight); svg.remove(); }); }); From 0de97d63847810e7a311fc6105d467dc59bbb935 Mon Sep 17 00:00:00 2001 From: Brandon Luong Date: Mon, 18 Aug 2014 17:08:52 -0700 Subject: [PATCH 3/5] Adding test messages and removing unneeded tests --- test/components/categoryAxisTests.ts | 13 ++++++------- test/tests.js | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/test/components/categoryAxisTests.ts b/test/components/categoryAxisTests.ts index 55c64e9762..3419b8e12f 100644 --- a/test/components/categoryAxisTests.ts +++ b/test/components/categoryAxisTests.ts @@ -33,17 +33,16 @@ describe("Category Axes", () => { ca.renderTo(svg); var axisWidth = ca.width(); - assert.operator(axisWidth, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing tickLabelPadding increases width"); axisWidth = ca.width(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing gutter increases width"); axisWidth = ca.width(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing tickLength increases width"); svg.remove(); }); @@ -57,15 +56,15 @@ describe("Category Axes", () => { var axisHeight = ca.height(); assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.height(), ">", axisHeight); + assert.operator(ca.height(), ">", axisHeight, "increasing tickLabelPadding increases height"); axisHeight = ca.height(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisHeight); + assert.operator(ca.width(), ">", axisHeight, "increasing gutter increases height"); axisHeight = ca.height(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.height(), ">", axisHeight); + assert.operator(ca.height(), ">", axisHeight, "increasing ticklength increases height"); svg.remove(); }); diff --git a/test/tests.js b/test/tests.js index 1861fb537e..77bc3063a3 100644 --- a/test/tests.js +++ b/test/tests.js @@ -643,15 +643,14 @@ describe("Category Axes", function () { var ca = new Plottable.Axis.Category(xScale, "left"); ca.renderTo(svg); var axisWidth = ca.width(); - assert.operator(axisWidth, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing tickLabelPadding increases width"); axisWidth = ca.width(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing gutter increases width"); axisWidth = ca.width(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.width(), ">", axisWidth); + assert.operator(ca.width(), ">", axisWidth, "increasing tickLength increases width"); svg.remove(); }); it("width and height account for gutter. ticklength, and padding on horizontal axes", function () { @@ -662,13 +661,13 @@ describe("Category Axes", function () { var axisHeight = ca.height(); assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.height(), ">", axisHeight); + assert.operator(ca.height(), ">", axisHeight, "increasing tickLabelPadding increases height"); axisHeight = ca.height(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisHeight); + assert.operator(ca.width(), ">", axisHeight, "increasing gutter increases height"); axisHeight = ca.height(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.height(), ">", axisHeight); + assert.operator(ca.height(), ">", axisHeight, "increasing ticklength increases height"); svg.remove(); }); }); From 7679bf706bb8cafc4d924be5ee4b29d74262569e Mon Sep 17 00:00:00 2001 From: Brandon Luong Date: Mon, 18 Aug 2014 17:15:12 -0700 Subject: [PATCH 4/5] Using closeTo --- test/components/categoryAxisTests.ts | 17 ++++++++--------- test/tests.js | 17 ++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/test/components/categoryAxisTests.ts b/test/components/categoryAxisTests.ts index 3419b8e12f..820c4f5933 100644 --- a/test/components/categoryAxisTests.ts +++ b/test/components/categoryAxisTests.ts @@ -26,7 +26,7 @@ describe("Category Axes", () => { svg.remove(); }); - it("width and height account for gutter. ticklength, and padding on vertical axes", () => { + it("width accounts for gutter. ticklength, and padding on vertical axes", () => { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "left"); @@ -34,37 +34,36 @@ describe("Category Axes", () => { var axisWidth = ca.width(); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing tickLabelPadding increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing tickLabelPadding increases width"); axisWidth = ca.width(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing gutter increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing gutter increases width"); axisWidth = ca.width(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing tickLength increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing tickLength increases width"); svg.remove(); }); - it("width and height account for gutter. ticklength, and padding on horizontal axes", () => { + it("height accounts for gutter. ticklength, and padding on horizontal axes", () => { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "bottom"); ca.renderTo(svg); var axisHeight = ca.height(); - assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.height(), ">", axisHeight, "increasing tickLabelPadding increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing tickLabelPadding increases height"); axisHeight = ca.height(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisHeight, "increasing gutter increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing gutter increases height"); axisHeight = ca.height(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.height(), ">", axisHeight, "increasing ticklength increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing ticklength increases height"); svg.remove(); }); diff --git a/test/tests.js b/test/tests.js index 77bc3063a3..d1c97abbc0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -637,37 +637,36 @@ describe("Category Axes", function () { assert.isFalse(s.wantsHeight, "it doesn't want height"); svg.remove(); }); - it("width and height account for gutter. ticklength, and padding on vertical axes", function () { + it("width accounts for gutter. ticklength, and padding on vertical axes", function () { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "left"); ca.renderTo(svg); var axisWidth = ca.width(); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing tickLabelPadding increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing tickLabelPadding increases width"); axisWidth = ca.width(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing gutter increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing gutter increases width"); axisWidth = ca.width(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.width(), ">", axisWidth, "increasing tickLength increases width"); + assert.closeTo(ca.width(), axisWidth + 5, 2, "increasing tickLength increases width"); svg.remove(); }); - it("width and height account for gutter. ticklength, and padding on horizontal axes", function () { + it("height accounts for gutter. ticklength, and padding on horizontal axes", function () { var svg = generateSVG(400, 400); var xScale = new Plottable.Scale.Ordinal().domain(["foo", "bar", "baz"]).range([400, 0]); var ca = new Plottable.Axis.Category(xScale, "bottom"); ca.renderTo(svg); var axisHeight = ca.height(); - assert.operator(axisHeight, ">", ca.tickLabelPadding() + ca.gutter() + ca.tickLength()); ca.tickLabelPadding(ca.tickLabelPadding() + 5); - assert.operator(ca.height(), ">", axisHeight, "increasing tickLabelPadding increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing tickLabelPadding increases height"); axisHeight = ca.height(); ca.gutter(ca.gutter() + 5); - assert.operator(ca.width(), ">", axisHeight, "increasing gutter increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing gutter increases height"); axisHeight = ca.height(); ca.tickLength(ca.tickLength() + 5); - assert.operator(ca.height(), ">", axisHeight, "increasing ticklength increases height"); + assert.closeTo(ca.height(), axisHeight + 5, 2, "increasing ticklength increases height"); svg.remove(); }); }); From 824c8c8390e80af29bf91a396125f6405a88b0fd Mon Sep 17 00:00:00 2001 From: Brandon Luong Date: Mon, 18 Aug 2014 20:12:53 -0700 Subject: [PATCH 5/5] Updating built files --- plottable.d.ts | 2299 +++++++----------------------------------------- test/tests.js | 1413 +++-------------------------- 2 files changed, 459 insertions(+), 3253 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index f38fdfb02d..be37db8c79 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -2,71 +2,16 @@ declare module Plottable { module Util { module Methods { - /** - * Checks if x is between a and b. - * - * @param {number} x The value to test if in range - * @param {number} a The beginning of the (inclusive) range - * @param {number} b The ending of the (inclusive) range - * @return {boolean} Whether x is in [a, b] - */ function inRange(x: number, a: number, b: number): boolean; - /** Print a warning message to the console, if it is available. - * - * @param {string} The warnings to print - */ function warn(warning: string): void; - /** - * Takes two arrays of numbers and adds them together - * - * @param {number[]} alist The first array of numbers - * @param {number[]} blist The second array of numbers - * @return {number[]} An array of numbers where x[i] = alist[i] + blist[i] - */ function addArrays(alist: number[], blist: number[]): number[]; - /** - * Takes two sets and returns the intersection - * - * @param {D3.Set} set1 The first set - * @param {D3.Set} set2 The second set - * @return {D3.Set} A set that contains elements that appear in both set1 and set2 - */ function intersection(set1: D3.Set, set2: D3.Set): D3.Set; - /** - * Takes two sets and returns the union - * - * @param{D3.Set} set1 The first set - * @param{D3.Set} set2 The second set - * @return{D3.Set} A set that contains elements that appear in either set1 or set2 - */ function union(set1: D3.Set, set2: D3.Set): D3.Set; function uniq(strings: string[]): string[]; function uniqNumbers(a: number[]): number[]; - /** - * Creates an array of length `count`, filled with value or (if value is a function), value() - * - * @param {any} value The value to fill the array with, or, if a function, a generator for values - * @param {number} count The length of the array to generate - * @return {any[]} - */ function createFilledArray(value: any, count: number): any[]; - /** - * @param {T[][]} a The 2D array that will have its elements joined together. - * @return {T[]} Every array in a, concatenated together in the order they appear. - */ function flatten(a: T[][]): T[]; - /** - * Check if two arrays are equal by strict equality. - */ function arrayEq(a: T[], b: T[]): boolean; - /** - * @param {any} a Object to check against b for equality. - * @param {any} b Object to check against a for equality. - * - * @returns {boolean} whether or not two objects share the same keys, and - * values associated with those keys. Values will be compared - * with ===. - */ function objEq(a: any, b: any): boolean; } } @@ -76,42 +21,6 @@ declare module Plottable { declare module Plottable { module Util { module OpenSource { - /** - * Returns the sortedIndex for inserting a value into an array. - * Takes a number and an array of numbers OR an array of objects and an accessor that returns a number. - * @param {number} value: The numerical value to insert - * @param {any[]} arr: Array to find insertion index, can be number[] or any[] (if accessor provided) - * @param {IAccessor} accessor: If provided, this function is called on members of arr to determine insertion index - * @returns {number} The insertion index. - * The behavior is undefined for arrays that are unsorted - * If there are multiple valid insertion indices that maintain sorted order (e.g. addign 1 to [1,1,1,1,1]) then - * the behavior must satisfy that the array is sorted post-insertion, but is otherwise unspecified. - * This is a modified version of Underscore.js's implementation of sortedIndex. - * Underscore.js is released under the MIT License: - * Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative - * Reporters & Editors - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ function sortedIndex(val: number, arr: number[]): number; function sortedIndex(val: number, arr: any[], accessor: IAccessor): number; } @@ -122,9 +31,9 @@ declare module Plottable { declare module Plottable { module Util { class IDCounter { - public increment(id: any): number; - public decrement(id: any): number; - public get(id: any): number; + increment(id: any): number; + decrement(id: any): number; + get(id: any): number; } } } @@ -132,63 +41,14 @@ declare module Plottable { declare module Plottable { module Util { - /** - * An associative array that can be keyed by anything (inc objects). - * Uses pointer equality checks which is why this works. - * This power has a price: everything is linear time since it is actually backed by an array... - */ class StrictEqualityAssociativeArray { - /** - * Set a new key/value pair in the store. - * - * @param {any} key Key to set in the store - * @param {any} value Value to set in the store - * @return {boolean} True if key already in store, false otherwise - */ - public set(key: any, value: any): boolean; - /** - * Get a value from the store, given a key. - * - * @param {any} key Key associated with value to retrieve - * @return {any} Value if found, undefined otherwise - */ - public get(key: any): any; - /** - * Test whether store has a value associated with given key. - * - * Will return true if there is a key/value entry, - * even if the value is explicitly `undefined`. - * - * @param {any} key Key to test for presence of an entry - * @return {boolean} Whether there was a matching entry for that key - */ - public has(key: any): boolean; - /** - * Return an array of the values in the key-value store - * - * @return {any[]} The values in the store - */ - public values(): any[]; - /** - * Return an array of keys in the key-value store - * - * @return {any[]} The keys in the store - */ - public keys(): any[]; - /** - * Execute a callback for each entry in the array. - * - * @param {(key: any, val?: any, index?: number) => any} callback The callback to eecute - * @return {any[]} The results of mapping the callback over the entries - */ - public map(cb: (key?: any, val?: any, index?: number) => any): any[]; - /** - * Delete a key from the key-value store. Return whether the key was present. - * - * @param {any} The key to remove - * @return {boolean} Whether a matching entry was found and removed - */ - public delete(key: any): boolean; + set(key: any, value: any): boolean; + get(key: any): any; + has(key: any): boolean; + values(): any[]; + keys(): any[]; + map(cb: (key?: any, val?: any, index?: number) => any): any[]; + delete(key: any): boolean; } } } @@ -197,36 +57,9 @@ declare module Plottable { declare module Plottable { module Util { class Cache { - /** - * @constructor - * - * @param {string} compute The function whose results will be cached. - * @param {string} [canonicalKey] If present, when clear() is called, - * this key will be re-computed. If its result hasn't been changed, - * the cache will not be cleared. - * @param {(v: T, w: T) => boolean} [valueEq] - * Used to determine if the value of canonicalKey has changed. - * If omitted, defaults to === comparision. - */ constructor(compute: (k: string) => T, canonicalKey?: string, valueEq?: (v: T, w: T) => boolean); - /** - * Attempt to look up k in the cache, computing the result if it isn't - * found. - * - * @param {string} k The key to look up in the cache. - * @return {T} The value associated with k; the result of compute(k). - */ - public get(k: string): T; - /** - * Reset the cache empty. - * - * If canonicalKey was provided at construction, compute(canonicalKey) - * will be re-run. If the result matches what is already in the cache, - * it will not clear the cache. - * - * @return {Cache} The calling Cache. - */ - public clear(): Cache; + get(k: string): T; + clear(): Cache; } } } @@ -243,45 +76,12 @@ declare module Plottable { interface TextMeasurer { (s: string): Dimensions; } - /** - * Returns a quasi-pure function of typesignature (t: string) => Dimensions which measures height and width of text - * in the given text selection - * - * @param {D3.Selection} selection: A temporary text selection that the string will be placed into for measurement. - * Will be removed on function creation and appended only for measurement. - * @returns {Dimensions} width and height of the text - */ function getTextMeasurer(selection: D3.Selection): TextMeasurer; - /** - * This class will measure text by measuring each character individually, - * then adding up the dimensions. It will also cache the dimensions of each - * letter. - */ class CachingCharacterMeasurer { - /** - * @param {string} s The string to be measured. - * @return {Dimensions} The width and height of the measured text. - */ - public measure: TextMeasurer; - /** - * @param {D3.Selection} textSelection The element that will have text inserted into - * it in order to measure text. The styles present for text in - * this element will to the text being measured. - */ + measure: TextMeasurer; constructor(textSelection: D3.Selection); - /** - * Clear the cache, if it seems that the text has changed size. - */ - public clear(): CachingCharacterMeasurer; + clear(): CachingCharacterMeasurer; } - /** - * Gets a truncated version of a sting that fits in the available space, given the element in which to draw the text - * - * @param {string} text: The string to be truncated - * @param {number} availableWidth: The available width, in pixels - * @param {D3.Selection} element: The text element used to measure the text - * @returns {string} text - the shortened text - */ function getTruncatedText(text: string, availableWidth: number, measurer: TextMeasurer): string; function writeLineHorizontally(line: string, g: D3.Selection, width: number, height: number, xAlign?: string, yAlign?: string): { width: number; @@ -301,12 +101,6 @@ declare module Plottable { xAlign: string; yAlign: string; } - /** - * @param {write} [IWriteOptions] If supplied, the text will be written - * To the given g. Will align the text vertically if it seems like - * that is appropriate. - * Returns an IWriteTextResult with info on whether the text fit, and how much width/height was used. - */ function writeText(text: string, width: number, height: number, tm: TextMeasurer, horizontally?: boolean, write?: IWriteOptions): IWriteTextResult; } } @@ -321,16 +115,7 @@ declare module Plottable { lines: string[]; textFits: boolean; } - /** - * Takes a block of text, a width and height to fit it in, and a 2-d text measurement function. - * Wraps words and fits as much of the text as possible into the given width and height. - */ function breakTextToFitRect(text: string, width: number, height: number, measureText: Text.TextMeasurer): IWrappedText; - /** - * Determines if it is possible to fit a given text within width without breaking any of the words. - * Simple algorithm, split the text up into tokens, and make sure that the widest token doesn't exceed - * allowed width. - */ function canWrapWithoutBreakingWords(text: string, width: number, widthMeasure: (s: string) => number): boolean; } } @@ -339,11 +124,6 @@ declare module Plottable { declare module Plottable { module Util { module DOM { - /** - * Gets the bounding box of an element. - * @param {D3.Selection} element - * @returns {SVGRed} The bounding box. - */ function getBBox(element: D3.Selection): SVGRect; var POLYFILL_TIMEOUT_MSEC: number; function requestAnimationFramePolyfill(fn: () => any): void; @@ -364,76 +144,13 @@ declare module Plottable { } var MILLISECONDS_IN_ONE_DAY: number; class Formatters { - /** - * Creates a formatter for currency values. - * - * @param {number} [precision] The number of decimal places to show (default 2). - * @param {string} [symbol] The currency symbol to use (default "$"). - * @param {boolean} [prefix] Whether to prepend or append the currency symbol (default true). - * @param {boolean} [onlyShowUnchanged] Whether to return a value if value changes after formatting (default true). - * - * @returns {Formatter} A formatter for currency values. - */ static currency(precision?: number, symbol?: string, prefix?: boolean, onlyShowUnchanged?: boolean): (d: any) => string; - /** - * Creates a formatter that displays exactly [precision] decimal places. - * - * @param {number} [precision] The number of decimal places to show (default 3). - * @param {boolean} [onlyShowUnchanged] Whether to return a value if value changes after formatting (default true). - * - * @returns {Formatter} A formatter that displays exactly [precision] decimal places. - */ static fixed(precision?: number, onlyShowUnchanged?: boolean): (d: any) => string; - /** - * Creates a formatter that formats numbers to show no more than - * [precision] decimal places. All other values are stringified. - * - * @param {number} [precision] The number of decimal places to show (default 3). - * @param {boolean} [onlyShowUnchanged] Whether to return a value if value changes after formatting (default true). - * - * @returns {Formatter} A formatter for general values. - */ static general(precision?: number, onlyShowUnchanged?: boolean): (d: any) => string; - /** - * Creates a formatter that stringifies its input. - * - * @returns {Formatter} A formatter that stringifies its input. - */ static identity(): (d: any) => string; - /** - * Creates a formatter for percentage values. - * Multiplies the input by 100 and appends "%". - * - * @param {number} [precision] The number of decimal places to show (default 0). - * @param {boolean} [onlyShowUnchanged] Whether to return a value if value changes after formatting (default true). - * - * @returns {Formatter} A formatter for percentage values. - */ static percentage(precision?: number, onlyShowUnchanged?: boolean): (d: any) => string; - /** - * Creates a formatter for values that displays [precision] significant figures - * and puts SI notation. - * - * @param {number} [precision] The number of significant figures to show (default 3). - * - * @returns {Formatter} A formatter for SI values. - */ static siSuffix(precision?: number): (d: any) => string; - /** - * Creates a formatter that displays dates. - * - * @returns {Formatter} A formatter for time/date values. - */ static time(): (d: any) => string; - /** - * Creates a formatter for relative dates. - * - * @param {number} baseValue The start date (as epoch time) used in computing relative dates (default 0) - * @param {number} increment The unit used in calculating relative date values (default MILLISECONDS_IN_ONE_DAY) - * @param {string} label The label to append to the formatted string (default "") - * - * @returns {Formatter} A formatter for time/date values. - */ static relativeDate(baseValue?: number, increment?: number, label?: string): (d: any) => string; } } @@ -473,119 +190,32 @@ declare module Plottable { declare module Plottable { module Core { - /** - * This interface represents anything in Plottable which can have a listener attached. - * Listeners attach by referencing the Listenable's broadcaster, and calling registerListener - * on it. - * - * e.g.: - * listenable: Plottable.IListenable; - * listenable.broadcaster.registerListener(callbackToCallOnBroadcast) - */ interface IListenable { broadcaster: Broadcaster; } - /** - * This interface represents the callback that should be passed to the Broadcaster on a Listenable. - * - * The callback will be called with the attached Listenable as the first object, and optional arguments - * as the subsequent arguments. - * - * The Listenable is passed as the first argument so that it is easy for the callback to reference the - * current state of the Listenable in the resolution logic. - */ interface IBroadcasterCallback { (listenable: IListenable, ...args: any[]): any; } - /** - * The Broadcaster class is owned by an IListenable. Third parties can register and deregister listeners - * from the broadcaster. When the broadcaster.broadcast method is activated, all registered callbacks are - * called. The registered callbacks are called with the registered Listenable that the broadcaster is attached - * to, along with optional arguments passed to the `broadcast` method. - * - * The listeners are called synchronously. - */ - class Broadcaster extends Abstract.PlottableObject { - public listenable: IListenable; - /** - * Construct a broadcaster, taking the Listenable that the broadcaster will be attached to. - * - * @constructor - * @param {IListenable} listenable The Listenable-object that this broadcaster is attached to. - */ + class Broadcaster extends Plottable.Abstract.PlottableObject { + listenable: IListenable; constructor(listenable: IListenable); - /** - * Registers a callback to be called when the broadcast method is called. Also takes a key which - * is used to support deregistering the same callback later, by passing in the same key. - * If there is already a callback associated with that key, then the callback will be replaced. - * - * @param key The key associated with the callback. Key uniqueness is determined by deep equality. - * @param {IBroadcasterCallback} callback A callback to be called when the Scale's domain changes. - * @returns {Broadcaster} this object - */ - public registerListener(key: any, callback: IBroadcasterCallback): Broadcaster; - /** - * Call all listening callbacks, optionally with arguments passed through. - * - * @param ...args A variable number of optional arguments - * @returns {Broadcaster} this object - */ - public broadcast(...args: any[]): Broadcaster; - /** - * Deregisters the callback associated with a key. - * - * @param key The key to deregister. - * @returns {Broadcaster} this object - */ - public deregisterListener(key: any): Broadcaster; - /** - * Deregisters all listeners and callbacks associated with the broadcaster. - * - * @returns {Broadcaster} this object - */ - public deregisterAllListeners(): void; - } - } -} - - -declare module Plottable { - class DataSource extends Abstract.PlottableObject implements Core.IListenable { - public broadcaster: Core.Broadcaster; - /** - * Creates a new DataSource. - * - * @constructor - * @param {any[]} data - * @param {any} metadata An object containing additional information. - */ + registerListener(key: any, callback: IBroadcasterCallback): Broadcaster; + broadcast(...args: any[]): Broadcaster; + deregisterListener(key: any): Broadcaster; + deregisterAllListeners(): void; + } + } +} + + +declare module Plottable { + class DataSource extends Plottable.Abstract.PlottableObject implements Plottable.Core.IListenable { + broadcaster: any; constructor(data?: any[], metadata?: any); - /** - * Gets the data. - * - * @returns {any[]} The current data. - */ - public data(): any[]; - /** - * Sets new data. - * - * @param {any[]} data The new data. - * @returns {DataSource} The calling DataSource. - */ - public data(data: any[]): DataSource; - /** - * Gets the metadata. - * - * @returns {any} The current metadata. - */ - public metadata(): any; - /** - * Sets the metadata. - * - * @param {any} metadata The new metadata. - * @returns {DataSource} The calling DataSource. - */ - public metadata(metadata: any): DataSource; + data(): any[]; + data(data: any[]): DataSource; + metadata(): any; + metadata(metadata: any): DataSource; } } @@ -593,107 +223,29 @@ declare module Plottable { declare module Plottable { module Abstract { class Component extends PlottableObject { - public element: D3.Selection; - public content: D3.Selection; - public backgroundContainer: D3.Selection; - public foregroundContainer: D3.Selection; - public clipPathEnabled: boolean; - public availableWidth: number; - public availableHeight: number; - public xOrigin: number; - public yOrigin: number; + element: D3.Selection; + content: D3.Selection; + backgroundContainer: D3.Selection; + foregroundContainer: D3.Selection; + clipPathEnabled: boolean; + availableWidth: number; + availableHeight: number; + xOrigin: number; + yOrigin: number; static AUTORESIZE_BY_DEFAULT: boolean; - /** - * Renders the Component into a given DOM element. - * - * @param {String|D3.Selection} element A D3 selection or a selector for getting the element to render into. - * @return {Component} The calling component. - */ - public renderTo(element: any): Component; - /** - * Cause the Component to recompute layout and redraw. If passed arguments, will resize the root SVG it lives in. - * - * @param {number} [availableWidth] - the width of the container element - * @param {number} [availableHeight] - the height of the container element - */ - public resize(width?: number, height?: number): Component; - /** - * Enables and disables auto-resize. - * - * If enabled, window resizes will enqueue this component for a re-layout - * and re-render. Animations are disabled during window resizes when auto- - * resize is enabled. - * - * @param {boolean} flag - Enables (true) or disables (false) auto-resize. - */ - public autoResize(flag: boolean): Component; - /** - * Sets the x alignment of the Component. - * - * @param {string} alignment The x alignment of the Component (one of LEFT/CENTER/RIGHT). - * @returns {Component} The calling Component. - */ - public xAlign(alignment: string): Component; - /** - * Sets the y alignment of the Component. - * - * @param {string} alignment The y alignment of the Component (one of TOP/CENTER/BOTTOM). - * @returns {Component} The calling Component. - */ - public yAlign(alignment: string): Component; - /** - * Sets the x offset of the Component. - * - * @param {number} offset The desired x offset, in pixels. - * @returns {Component} The calling Component. - */ - public xOffset(offset: number): Component; - /** - * Sets the y offset of the Component. - * - * @param {number} offset The desired y offset, in pixels. - * @returns {Component} The calling Component. - */ - public yOffset(offset: number): Component; - /** - * Attaches an Interaction to the Component, so that the Interaction will listen for events on the Component. - * - * @param {Interaction} interaction The Interaction to attach to the Component. - * @return {Component} The calling Component. - */ - public registerInteraction(interaction: Interaction): Component; - /** - * Adds/removes a given CSS class to/from the Component, or checks if the Component has a particular CSS class. - * - * @param {string} cssClass The CSS class to add/remove/check for. - * @param {boolean} [addClass] Whether to add or remove the CSS class. If not supplied, checks for the CSS class. - * @return {boolean|Component} Whether the Component has the given CSS class, or the calling Component (if addClass is supplied). - */ - public classed(cssClass: string): boolean; - public classed(cssClass: string, addClass: boolean): Component; - /** - * Merges this Component with another Component, returning a ComponentGroup. - * There are four cases: - * Component + Component: Returns a ComponentGroup with both components inside it. - * ComponentGroup + Component: Returns the ComponentGroup with the Component appended. - * Component + ComponentGroup: Returns the ComponentGroup with the Component prepended. - * ComponentGroup + ComponentGroup: Returns a new ComponentGroup with two ComponentGroups inside it. - * - * @param {Component} c The component to merge in. - * @return {ComponentGroup} - */ - public merge(c: Component): Component.Group; - /** - * Detaches a Component from the DOM. The component can be reused. - * - * @returns The calling Component. - */ - public detach(): Component; - /** - * Removes a Component from the DOM and disconnects it from everything it's - * listening to (effectively destroying it). - */ - public remove(): void; + renderTo(element: any): Component; + resize(width?: number, height?: number): Component; + autoResize(flag: boolean): Component; + xAlign(alignment: string): Component; + yAlign(alignment: string): Component; + xOffset(offset: number): Component; + yOffset(offset: number): Component; + registerInteraction(interaction: Interaction): Component; + classed(cssClass: string): boolean; + classed(cssClass: string, addClass: boolean): Component; + merge(c: Component): Plottable.Component.Group; + detach(): Component; + remove(): void; } } } @@ -702,26 +254,10 @@ declare module Plottable { declare module Plottable { module Abstract { class ComponentContainer extends Component { - /** - * Returns a list of components in the ComponentContainer - * - * @returns{Component[]} the contained Components - */ - public components(): Component[]; - /** - * Returns true iff the ComponentContainer is empty. - * - * @returns {boolean} Whether the calling ComponentContainer is empty. - */ - public empty(): boolean; - /** - * Detaches all components contained in the ComponentContainer, and - * empties the ComponentContainer. - * - * @returns {ComponentContainer} The calling ComponentContainer - */ - public detachAll(): ComponentContainer; - public remove(): void; + components(): Component[]; + empty(): boolean; + detachAll(): ComponentContainer; + remove(): void; } } } @@ -729,15 +265,9 @@ declare module Plottable { declare module Plottable { module Component { - class Group extends Abstract.ComponentContainer { - /** - * Creates a ComponentGroup. - * - * @constructor - * @param {Component[]} [components] The Components in the Group. - */ - constructor(components?: Abstract.Component[]); - public merge(c: Abstract.Component): Group; + class Group extends Plottable.Abstract.ComponentContainer { + constructor(components?: Plottable.Abstract.Component[]); + merge(c: Plottable.Abstract.Component): Group; } } } @@ -753,49 +283,12 @@ declare module Plottable { wantsWidth: boolean; wantsHeight: boolean; } - class Table extends Abstract.ComponentContainer { - /** - * Creates a Table. - * - * @constructor - * @param {Component[][]} [rows] A 2-D array of the Components to place in the table. - * null can be used if a cell is empty. - */ - constructor(rows?: Abstract.Component[][]); - /** - * Adds a Component in the specified cell. - * - * @param {number} row The row in which to add the Component. - * @param {number} col The column in which to add the Component. - * @param {Component} component The Component to be added. - */ - public addComponent(row: number, col: number, component: Abstract.Component): Table; - /** - * Sets the row and column padding on the Table. - * - * @param {number} rowPadding The padding above and below each row, in pixels. - * @param {number} colPadding the padding to the left and right of each column, in pixels. - * @returns {Table} The calling Table. - */ - public padding(rowPadding: number, colPadding: number): Table; - /** - * Sets the layout weight of a particular row. - * Space is allocated to rows based on their weight. Rows with higher weights receive proportionally more space. - * - * @param {number} index The index of the row. - * @param {number} weight The weight to be set on the row. - * @returns {Table} The calling Table. - */ - public rowWeight(index: number, weight: number): Table; - /** - * Sets the layout weight of a particular column. - * Space is allocated to columns based on their weight. Columns with higher weights receive proportionally more space. - * - * @param {number} index The index of the column. - * @param {number} weight The weight to be set on the column. - * @returns {Table} The calling Table. - */ - public colWeight(index: number, weight: number): Table; + class Table extends Plottable.Abstract.ComponentContainer { + constructor(rows?: Plottable.Abstract.Component[][]); + addComponent(row: number, col: number, component: Plottable.Abstract.Component): Table; + padding(rowPadding: number, colPadding: number): Table; + rowWeight(index: number, weight: number): Table; + colWeight(index: number, weight: number): Table; } } } @@ -803,77 +296,18 @@ declare module Plottable { declare module Plottable { module Abstract { - class Scale extends PlottableObject implements Core.IListenable { - public broadcaster: Core.Broadcaster; - /** - * Creates a new Scale. - * - * @constructor - * @param {D3.Scale.Scale} scale The D3 scale backing the Scale. - */ + class Scale extends PlottableObject implements Plottable.Core.IListenable { + broadcaster: any; constructor(scale: D3.Scale.Scale); - /** - * Modify the domain on the scale so that it includes the extent of all - * perspectives it depends on. Extent: The (min, max) pair for a - * QuantitiativeScale, all covered strings for an OrdinalScale. - * Perspective: A combination of a DataSource and an Accessor that - * represents a view in to the data. - */ - public autoDomain(): Scale; - /** - * Returns the range value corresponding to a given domain value. - * - * @param value {any} A domain value to be scaled. - * @returns {any} The range value corresponding to the supplied domain value. - */ - public scale(value: any): any; - /** - * Gets the domain. - * - * @returns {any[]} The current domain. - */ - public domain(): any[]; - /** - * Sets the Scale's domain to the specified values. - * - * @param {any[]} values The new value for the domain. This array may - * contain more than 2 values if the scale type allows it (e.g. - * ordinal scales). Other scales such as quantitative scales accept - * only a 2-value extent array. - * @returns {Scale} The calling Scale. - */ - public domain(values: any[]): Scale; - /** - * Gets the range. - * - * @returns {any[]} The current range. - */ - public range(): any[]; - /** - * Sets the Scale's range to the specified values. - * - * @param {any[]} values The new values for the range. - * @returns {Scale} The calling Scale. - */ - public range(values: any[]): Scale; - /** - * Creates a copy of the Scale with the same domain and range but without any registered listeners. - * - * @returns {Scale} A copy of the calling Scale. - */ - public copy(): Scale; - /** - * When a renderer determines that the extent of a projector has changed, - * it will call this function. This function should ensure that - * the scale has a domain at least large enough to include extent. - * - * @param {number} rendererID A unique indentifier of the renderer sending - * the new extent. - * @param {string} attr The attribute being projected, e.g. "x", "y0", "r" - * @param {any[]} extent The new extent to be included in the scale. - */ - public updateExtent(plotProvidedKey: string, attr: string, extent: any[]): Scale; - public removeExtent(plotProvidedKey: string, attr: string): Scale; + autoDomain(): Scale; + scale(value: any): any; + domain(): any[]; + domain(values: any[]): Scale; + range(): any[]; + range(values: any[]): Scale; + copy(): Scale; + updateExtent(plotProvidedKey: string, attr: string, extent: any[]): Scale; + removeExtent(plotProvidedKey: string, attr: string): Scale; } } } @@ -882,55 +316,19 @@ declare module Plottable { declare module Plottable { module Abstract { class Plot extends Component { - public renderArea: D3.Selection; - public element: D3.Selection; - /** - * Creates a Plot. - * - * @constructor - * @param {any[]|DataSource} [dataset] The data or DataSource to be associated with this Plot. - */ + renderArea: D3.Selection; + element: D3.Selection; constructor(); constructor(dataset: any[]); constructor(dataset: DataSource); - public remove(): void; - /** - * Gets the Plot's DataSource. - * - * @return {DataSource} The current DataSource. - */ - public dataSource(): DataSource; - /** - * Sets the Plot's DataSource. - * - * @param {DataSource} source The DataSource the Plot should use. - * @return {Plot} The calling Plot. - */ - public dataSource(source: DataSource): Plot; - public project(attrToSet: string, accessor: any, scale?: Scale): Plot; - /** - * Enables or disables animation. - * - * @param {boolean} enabled Whether or not to animate. - */ - public animate(enabled: boolean): Plot; - public detach(): Plot; - /** - * Gets the animator associated with the specified Animator key. - * - * @param {string} animatorKey The key for the Animator. - * @return {Animator.IPlotAnimator} The Animator for the specified key. - */ - public animator(animatorKey: string): Animator.IPlotAnimator; - /** - * Sets the animator associated with the specified Animator key. - * - * @param {string} animatorKey The key for the Animator. - * @param {Animator.IPlotAnimator} animator An Animator to be assigned to - * the specified key. - * @return {Plot} The calling Plot. - */ - public animator(animatorKey: string, animator: Animator.IPlotAnimator): Plot; + remove(): void; + dataSource(): DataSource; + dataSource(source: DataSource): Plot; + project(attrToSet: string, accessor: any, scale?: Scale): Plot; + animate(enabled: boolean): Plot; + detach(): Plot; + animator(animatorKey: string): Plottable.Animator.IPlotAnimator; + animator(animatorKey: string, animator: Plottable.Animator.IPlotAnimator): Plot; } } } @@ -939,18 +337,10 @@ declare module Plottable { declare module Plottable { module Abstract { class XYPlot extends Plot { - public xScale: Scale; - public yScale: Scale; - /** - * Creates an XYPlot. - * - * @constructor - * @param {any[]|DataSource} [dataset] The data or DataSource to be associated with this Renderer. - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ + xScale: Scale; + yScale: Scale; constructor(dataset: any, xScale: Scale, yScale: Scale); - public project(attrToSet: string, accessor: any, scale?: Scale): XYPlot; + project(attrToSet: string, accessor: any, scale?: Scale): XYPlot; } } } @@ -959,52 +349,20 @@ declare module Plottable { declare module Plottable { interface DatasetDrawerKey { dataset: DataSource; - drawer: Abstract._Drawer; + drawer: Plottable.Abstract._Drawer; key: string; } module Abstract { class NewStylePlot extends XYPlot { - /** - * Creates a NewStylePlot. - * - * @constructor - * @param [Scale] xScale The x scale to use - * @param [Scale] yScale The y scale to use - */ constructor(xScale?: Scale, yScale?: Scale); - public remove(): void; - /** - * Adds a dataset to this plot. Identify this dataset with a key. - * - * A key is automatically generated if not supplied. - * - * @param {string} [key] The key of the dataset. - * @param {any[]|DataSource} dataset dataset to add. - * @return {NewStylePlot} The calling NewStylePlot. - */ - public addDataset(key: string, dataset: DataSource): NewStylePlot; - public addDataset(key: string, dataset: any[]): NewStylePlot; - public addDataset(dataset: DataSource): NewStylePlot; - public addDataset(dataset: any[]): NewStylePlot; - /** - * Gets the dataset order by key - * - * @return {string[]} a string array of the keys in order - */ - public datasetOrder(): string[]; - /** - * Sets the dataset order by key - * - * @param {string[]} order A string array which represents the order of the keys. This must be a permutation of existing keys. - */ - public datasetOrder(order: string[]): NewStylePlot; - /** - * Removes a dataset - * - * @param {string} key The key of the dataset - * @return {NewStylePlot} The calling NewStylePlot. - */ - public removeDataset(key: string): NewStylePlot; + remove(): void; + addDataset(key: string, dataset: DataSource): NewStylePlot; + addDataset(key: string, dataset: any[]): NewStylePlot; + addDataset(dataset: DataSource): NewStylePlot; + addDataset(dataset: any[]): NewStylePlot; + datasetOrder(): string[]; + datasetOrder(order: string[]): NewStylePlot; + removeDataset(key: string): NewStylePlot; } } } @@ -1018,13 +376,13 @@ declare module Plottable { render(): any; } class Immediate implements IRenderPolicy { - public render(): void; + render(): void; } class AnimationFrame implements IRenderPolicy { - public render(): void; + render(): void; } class Timeout implements IRenderPolicy { - public render(): void; + render(): void; } } } @@ -1034,32 +392,10 @@ declare module Plottable { declare module Plottable { module Core { - /** - * The RenderController is responsible for enqueueing and synchronizing - * layout and render calls for Plottable components. - * - * Layouts and renders occur inside an animation callback - * (window.requestAnimationFrame if available). - * - * If you require immediate rendering, call RenderController.flush() to - * perform enqueued layout and rendering serially. - */ module RenderController { function setRenderPolicy(policy: RenderPolicy.IRenderPolicy): any; - /** - * If the RenderController is enabled, we enqueue the component for - * render. Otherwise, it is rendered immediately. - * - * @param {Abstract.Component} component Any Plottable component. - */ - function registerToRender(c: Abstract.Component): void; - /** - * If the RenderController is enabled, we enqueue the component for - * layout and render. Otherwise, it is rendered immediately. - * - * @param {Abstract.Component} component Any Plottable component. - */ - function registerToComputeLayout(c: Abstract.Component): void; + function registerToRender(c: Plottable.Abstract.Component): void; + function registerToComputeLayout(c: Plottable.Abstract.Component): void; function flush(): void; } } @@ -1068,41 +404,11 @@ declare module Plottable { declare module Plottable { module Core { - /** - * The ResizeBroadcaster will broadcast a notification to any registered - * components when the window is resized. - * - * The broadcaster and single event listener are lazily constructed. - * - * Upon resize, the _resized flag will be set to true until after the next - * flush of the RenderController. This is used, for example, to disable - * animations during resize. - */ module ResizeBroadcaster { - /** - * Returns true if the window has been resized and the RenderController - * has not yet been flushed. - */ function resizing(): boolean; function clearResizing(): any; - /** - * Registers a component. - * - * When the window is resized, we invoke ._invalidateLayout() on the - * component, which will enqueue the component for layout and rendering - * with the RenderController. - * - * @param {Abstract.Component} component Any Plottable component. - */ - function register(c: Abstract.Component): void; - /** - * Deregisters the components. - * - * The component will no longer receive updates on window resize. - * - * @param {Abstract.Component} component Any Plottable component. - */ - function deregister(c: Abstract.Component): void; + function register(c: Plottable.Abstract.Component): void; + function deregister(c: Plottable.Abstract.Component): void; } } } @@ -1111,18 +417,7 @@ declare module Plottable { declare module Plottable { module Animator { interface IPlotAnimator { - /** - * Applies the supplied attributes to a D3.Selection with some animation. - * - * @param {D3.Selection} selection The update selection or transition selection that we wish to animate. - * @param {IAttributeToProjector} attrToProjector The set of - * IAccessors that we will use to set attributes on the selection. - * @param {Abstract.Plot} plot The plot being animated. - * @return {D3.Selection} Animators should return the selection or - * transition object so that plots may chain the transitions between - * animators. - */ - animate(selection: any, attrToProjector: IAttributeToProjector, plot: Abstract.Plot): any; + animate(selection: any, attrToProjector: IAttributeToProjector, plot: Plottable.Abstract.Plot): any; } interface IPlotAnimatorMap { [animatorKey: string]: IPlotAnimator; @@ -1147,7 +442,7 @@ declare module Plottable { } interface _IProjector { accessor: IAccessor; - scale?: Abstract.Scale; + scale?: Plottable.Abstract.Scale; attribute: string; } interface IAttributeToProjector { @@ -1182,94 +477,14 @@ declare module Plottable { declare module Plottable { class Domainer { - /** - * @param {(extents: any[][]) => any[]} combineExtents - * If present, this function will be used by the Domainer to merge - * all the extents that are present on a scale. - * - * A plot may draw multiple things relative to a scale, e.g. - * different stocks over time. The plot computes their extents, - * which are a [min, max] pair. combineExtents is responsible for - * merging them all into one [min, max] pair. It defaults to taking - * the min of the first elements and the max of the second arguments. - */ constructor(combineExtents?: (extents: any[][]) => any[]); - /** - * @param {any[][]} extents The list of extents to be reduced to a single - * extent. - * @param {Abstract.QuantitativeScale} scale - * Since nice() must do different things depending on Linear, Log, - * or Time scale, the scale must be passed in for nice() to work. - * @return {any[]} The domain, as a merging of all exents, as a [min, max] - * pair. - */ - public computeDomain(extents: any[][], scale: Abstract.QuantitativeScale): any[]; - /** - * Sets the Domainer to pad by a given ratio. - * - * @param {number} [padProportion] Proportionally how much bigger the - * new domain should be (0.05 = 5% larger). - * - * A domainer will pad equal visual amounts on each side. - * On a linear scale, this means both sides are padded the same - * amount: [10, 20] will be padded to [5, 25]. - * On a log scale, the top will be padded more than the bottom, so - * [10, 100] will be padded to [1, 1000]. - * - * @return {Domainer} The calling Domainer. - */ - public pad(padProportion?: number): Domainer; - /** - * Add a padding exception, a value that will not be padded at either end of the domain. - * - * Eg, if a padding exception is added at x=0, then [0, 100] will pad to [0, 105] instead of [-2.5, 102.5]. - * If a key is provided, it will be registered under that key with standard map semantics. (Overwrite / remove by key) - * If a key is not provided, it will be added with set semantics (Can be removed by value) - * - * @param {any} exception The padding exception to add. - * @param string [key] The key to register the exception under. - * @return Domainer The calling domainer - */ - public addPaddingException(exception: any, key?: string): Domainer; - /** - * Remove a padding exception, allowing the domain to pad out that value again. - * - * If a string is provided, it is assumed to be a key and the exception associated with that key is removed. - * If a non-string is provdied, it is assumed to be an unkeyed exception and that exception is removed. - * - * @param {any} keyOrException The key for the value to remove, or the value to remove - * @return Domainer The calling domainer - */ - public removePaddingException(keyOrException: any): Domainer; - /** - * Add an included value, a value that must be included inside the domain. - * - * Eg, if a value exception is added at x=0, then [50, 100] will expand to [0, 100] rather than [50, 100]. - * If a key is provided, it will be registered under that key with standard map semantics. (Overwrite / remove by key) - * If a key is not provided, it will be added with set semantics (Can be removed by value) - * - * @param {any} value The included value to add. - * @param string [key] The key to register the value under. - * @return Domainer The calling domainer - */ - public addIncludedValue(value: any, key?: string): Domainer; - /** - * Remove an included value, allowing the domain to not include that value gain again. - * - * If a string is provided, it is assumed to be a key and the value associated with that key is removed. - * If a non-string is provdied, it is assumed to be an unkeyed value and that value is removed. - * - * @param {any} keyOrException The key for the value to remove, or the value to remove - * @return Domainer The calling domainer - */ - public removeIncludedValue(valueOrKey: any): Domainer; - /** - * Extends the scale's domain so it starts and ends with "nice" values. - * - * @param {number} [count] The number of ticks that should fit inside the new domain. - * @return {Domainer} The calling Domainer. - */ - public nice(count?: number): Domainer; + computeDomain(extents: any[][], scale: Plottable.Abstract.QuantitativeScale): any[]; + pad(padProportion?: number): Domainer; + addPaddingException(exception: any, key?: string): Domainer; + removePaddingException(keyOrException: any): Domainer; + addIncludedValue(value: any, key?: string): Domainer; + removeIncludedValue(valueOrKey: any): Domainer; + nice(count?: number): Domainer; } } @@ -1277,89 +492,20 @@ declare module Plottable { declare module Plottable { module Abstract { class QuantitativeScale extends Scale { - /** - * Creates a new QuantitativeScale. - * - * @constructor - * @param {D3.Scale.QuantitativeScale} scale The D3 QuantitativeScale backing the QuantitativeScale. - */ constructor(scale: D3.Scale.QuantitativeScale); - /** - * Retrieves the domain value corresponding to a supplied range value. - * - * @param {number} value: A value from the Scale's range. - * @returns {number} The domain value corresponding to the supplied range value. - */ - public invert(value: number): number; - /** - * Creates a copy of the QuantitativeScale with the same domain and range but without any registered listeners. - * - * @returns {QuantitativeScale} A copy of the calling QuantitativeScale. - */ - public copy(): QuantitativeScale; - public domain(): any[]; - public domain(values: any[]): QuantitativeScale; - /** - * Sets or gets the QuantitativeScale's output interpolator - * - * @param {D3.Transition.Interpolate} [factory] The output interpolator to use. - * @returns {D3.Transition.Interpolate|QuantitativeScale} The current output interpolator, or the calling QuantitativeScale. - */ - public interpolate(): D3.Transition.Interpolate; - public interpolate(factory: D3.Transition.Interpolate): QuantitativeScale; - /** - * Sets the range of the QuantitativeScale and sets the interpolator to d3.interpolateRound. - * - * @param {number[]} values The new range value for the range. - */ - public rangeRound(values: number[]): QuantitativeScale; - /** - * Gets the clamp status of the QuantitativeScale (whether to cut off values outside the ouput range). - * - * @returns {boolean} The current clamp status. - */ - public clamp(): boolean; - /** - * Sets the clamp status of the QuantitativeScale (whether to cut off values outside the ouput range). - * - * @param {boolean} clamp Whether or not to clamp the QuantitativeScale. - * @returns {QuantitativeScale} The calling QuantitativeScale. - */ - public clamp(clamp: boolean): QuantitativeScale; - /** - * Generates tick values. - * - * @param {number} [count] The number of ticks to generate. - * @returns {any[]} The generated ticks. - */ - public ticks(count?: number): any[]; - /** - * Gets a tick formatting function for displaying tick values. - * - * @param {number} count The number of ticks to be displayed - * @param {string} [format] A format specifier string. - * @returns {(n: number) => string} A formatting function. - */ - public tickFormat(count: number, format?: string): (n: number) => string; - /** - * Retrieve a Domainer of a scale. A Domainer is responsible for combining - * multiple extents into a single domain. - * - * @return {QuantitativeScale} The scale's current domainer. - */ - public domainer(): Domainer; - /** - * Sets a Domainer of a scale. A Domainer is responsible for combining - * multiple extents into a single domain. - * - * When you set domainer, we assume that you know what you want the domain - * to look like better that we do. Ensuring that the domain is padded, - * includes 0, etc., will be the responsability of the new domainer. - * - * @param {Domainer} domainer The domainer to be set. - * @return {QuantitativeScale} The calling scale. - */ - public domainer(domainer: Domainer): QuantitativeScale; + invert(value: number): number; + copy(): QuantitativeScale; + domain(): any[]; + domain(values: any[]): QuantitativeScale; + interpolate(): D3.Transition.Interpolate; + interpolate(factory: D3.Transition.Interpolate): QuantitativeScale; + rangeRound(values: number[]): QuantitativeScale; + clamp(): boolean; + clamp(clamp: boolean): QuantitativeScale; + ticks(count?: number): any[]; + tickFormat(count: number, format?: string): (n: number) => string; + domainer(): Domainer; + domainer(domainer: Domainer): QuantitativeScale; } } } @@ -1367,21 +513,10 @@ declare module Plottable { declare module Plottable { module Scale { - class Linear extends Abstract.QuantitativeScale { - /** - * Creates a new LinearScale. - * - * @constructor - * @param {D3.Scale.LinearScale} [scale] The D3 LinearScale backing the LinearScale. If not supplied, uses a default scale. - */ + class Linear extends Plottable.Abstract.QuantitativeScale { constructor(); constructor(scale: D3.Scale.LinearScale); - /** - * Creates a copy of the LinearScale with the same domain and range but without any registered listeners. - * - * @returns {LinearScale} A copy of the calling LinearScale. - */ - public copy(): Linear; + copy(): Linear; } } } @@ -1389,27 +524,10 @@ declare module Plottable { declare module Plottable { module Scale { - class Log extends Abstract.QuantitativeScale { - /** - * Creates a new Scale.Log. - * - * Warning: Log is deprecated; if possible, use ModifiedLog. Log scales are - * very unstable due to the fact that they can't handle 0 or negative - * numbers. The only time when you would want to use a Log scale over a - * ModifiedLog scale is if you're plotting very small data, such as all - * data < 1. - * - * @constructor - * @param {D3.Scale.LogScale} [scale] The D3 Scale.Log backing the Scale.Log. If not supplied, uses a default scale. - */ + class Log extends Plottable.Abstract.QuantitativeScale { constructor(); constructor(scale: D3.Scale.LogScale); - /** - * Creates a copy of the Scale.Log with the same domain and range but without any registered listeners. - * - * @returns {Scale.Log} A copy of the calling Scale.Log. - */ - public copy(): Log; + copy(): Log; } } } @@ -1417,51 +535,14 @@ declare module Plottable { declare module Plottable { module Scale { - class ModifiedLog extends Abstract.QuantitativeScale { - /** - * Creates a new Scale.ModifiedLog. - * - * A ModifiedLog scale acts as a regular log scale for large numbers. - * As it approaches 0, it gradually becomes linear. This means that the - * scale won't freak out if you give it 0 or a negative number, where an - * ordinary Log scale would. - * - * However, it does mean that scale will be effectively linear as values - * approach 0. If you want very small values on a log scale, you should use - * an ordinary Scale.Log instead. - * - * @constructor - * @param {number} [base] - * The base of the log. Defaults to 10, and must be > 1. - * - * For base <= x, scale(x) = log(x). - * - * For 0 < x < base, scale(x) will become more and more - * linear as it approaches 0. - * - * At x == 0, scale(x) == 0. - * - * For negative values, scale(-x) = -scale(x). - */ + class ModifiedLog extends Plottable.Abstract.QuantitativeScale { constructor(base?: number); - public scale(x: number): number; - public invert(x: number): number; - public ticks(count?: number): number[]; - public copy(): ModifiedLog; - /** - * @returns {boolean} - * Whether or not to return tick values other than powers of base. - * - * This defaults to false, so you'll normally only see ticks like - * [10, 100, 1000]. If you turn it on, you might see ticks values - * like [10, 50, 100, 500, 1000]. - */ - public showIntermediateTicks(): boolean; - /** - * @param {boolean} show - * Whether or not to return ticks values other than powers of the base. - */ - public showIntermediateTicks(show: boolean): ModifiedLog; + scale(x: number): number; + invert(x: number): number; + ticks(count?: number): number[]; + copy(): ModifiedLog; + showIntermediateTicks(): boolean; + showIntermediateTicks(show: boolean): ModifiedLog; } } } @@ -1469,72 +550,18 @@ declare module Plottable { declare module Plottable { module Scale { - class Ordinal extends Abstract.Scale { - /** - * Creates a new OrdinalScale. Domain and Range are set later. - * - * @constructor - */ + class Ordinal extends Plottable.Abstract.Scale { constructor(scale?: D3.Scale.OrdinalScale); - /** - * Gets the domain. - * - * @returns {any[]} The current domain. - */ - public domain(): any[]; - /** - * Sets the domain. - * - * @param {any[]} values The new values for the domain. This array may contain more than 2 values. - * @returns {Ordinal} The calling Ordinal Scale. - */ - public domain(values: any[]): Ordinal; - /** - * Gets the range of pixels spanned by the Ordinal Scale. - * - * @returns {number[]} The pixel range. - */ - public range(): number[]; - /** - * Sets the range of pixels spanned by the Ordinal Scale. - * - * @param {number[]} values The pixel range to to be spanend by the scale. - * @returns {Ordinal} The calling Ordinal Scale. - */ - public range(values: number[]): Ordinal; - /** - * Returns the width of the range band. Only valid when rangeType is set to "bands". - * - * @returns {number} The range band width or 0 if rangeType isn't "bands". - */ - public rangeBand(): number; - public innerPadding(): number; - public fullBandStartAndWidth(v: any): number[]; - /** - * Gets the range type. - * - * @returns {string} The current range type. - */ - public rangeType(): string; - /** - * Sets the range type. - * - * @param {string} rangeType Either "points" or "bands" indicating the - * d3 method used to generate range bounds. - * @param {number} [outerPadding] The padding outside the range, - * proportional to the range step. - * @param {number} [innerPadding] The padding between bands in the range, - * proportional to the range step. This parameter is only used in - * "bands" type ranges. - * @returns {Ordinal} The calling Ordinal Scale. - */ - public rangeType(rangeType: string, outerPadding?: number, innerPadding?: number): Ordinal; - /** - * Creates a copy of the Scale with the same domain and range but without any registered listeners. - * - * @returns {Ordinal} A copy of the calling Scale. - */ - public copy(): Ordinal; + domain(): any[]; + domain(values: any[]): Ordinal; + range(): number[]; + range(values: number[]): Ordinal; + rangeBand(): number; + innerPadding(): number; + fullBandStartAndWidth(v: any): number[]; + rangeType(): string; + rangeType(rangeType: string, outerPadding?: number, innerPadding?: number): Ordinal; + copy(): Ordinal; } } } @@ -1542,15 +569,7 @@ declare module Plottable { declare module Plottable { module Scale { - class Color extends Abstract.Scale { - /** - * Creates a ColorScale. - * - * @constructor - * @param {string} [scaleType] the type of color scale to create - * (Category10/Category20/Category20b/Category20c). - * See https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors - */ + class Color extends Plottable.Abstract.Scale { constructor(scaleType?: string); } } @@ -1559,24 +578,13 @@ declare module Plottable { declare module Plottable { module Scale { - class Time extends Abstract.QuantitativeScale { - /** - * Creates a new Time Scale. - * - * @constructor - * @param {D3.Scale.Time} [scale] The D3 LinearScale backing the TimeScale. If not supplied, uses a default scale. - */ + class Time extends Plottable.Abstract.QuantitativeScale { constructor(); constructor(scale: D3.Scale.LinearScale); - public tickInterval(interval: D3.Time.Interval, step?: number): any[]; - public domain(): any[]; - public domain(values: any[]): Time; - /** - * Creates a copy of the TimeScale with the same domain and range but without any registered listeners. - * - * @returns {TimeScale} A copy of the calling TimeScale. - */ - public copy(): Time; + tickInterval(interval: D3.Time.Interval, step?: number): any[]; + domain(): any[]; + domain(values: any[]): Time; + copy(): Time; } } } @@ -1584,58 +592,13 @@ declare module Plottable { declare module Plottable { module Scale { - /** - * This class implements a color scale that takes quantitive input and - * interpolates between a list of color values. It returns a hex string - * representing the interpolated color. - * - * By default it generates a linear scale internally. - */ - class InterpolatedColor extends Abstract.QuantitativeScale { - /** - * Creates a InterpolatedColorScale. - * - * @constructor - * @param {string|string[]} [colorRange] the type of color scale to - * create. Default is "reds". @see {@link colorRange} for further - * options. - * @param {string} [scaleType] the type of underlying scale to use - * (linear/pow/log/sqrt). Default is "linear". @see {@link scaleType} - * for further options. - */ + class InterpolatedColor extends Plottable.Abstract.QuantitativeScale { constructor(colorRange?: any, scaleType?: string); - /** - * Gets the color range. - * - * @returns {string[]} the current color values for the range as strings. - */ - public colorRange(): string[]; - /** - * Sets the color range. - * - * @param {string|string[]} colorRange. If colorRange is one of - * (reds/blues/posneg), uses the built-in color groups. If colorRange - * is an array of strings with at least 2 values - * (e.g. ["#FF00FF", "red", "dodgerblue"], the resulting scale - * will interpolate between the color values across the domain. - * @returns {InterpolatedColor} The calling InterpolatedColor Scale. - */ - public colorRange(colorRange: any): InterpolatedColor; - /** - * Gets the internal scale type. - * - * @returns {string} The current scale type. - */ - public scaleType(): string; - /** - * Sets the internal scale type. - * - * @param {string} scaleType. The type of d3 scale to use internally. - * (linear/log/sqrt/pow). - * @returns {InterpolatedColor} The calling InterpolatedColor Scale. - */ - public scaleType(scaleType: string): InterpolatedColor; - public autoDomain(): InterpolatedColor; + colorRange(): string[]; + colorRange(colorRange: any): InterpolatedColor; + scaleType(): string; + scaleType(scaleType: string): InterpolatedColor; + autoDomain(): InterpolatedColor; } } } @@ -1644,14 +607,8 @@ declare module Plottable { declare module Plottable { module Util { class ScaleDomainCoordinator { - /** - * Creates a ScaleDomainCoordinator. - * - * @constructor - * @param {Scale[]} scales A list of scales whose domains should be linked. - */ - constructor(scales: Abstract.Scale[]); - public rescale(scale: Abstract.Scale): void; + constructor(scales: Plottable.Abstract.Scale[]); + rescale(scale: Plottable.Abstract.Scale): void; } } } @@ -1660,26 +617,11 @@ declare module Plottable { declare module Plottable { module Abstract { class _Drawer { - public renderArea: D3.Selection; - public key: string; - /** - * Creates a Drawer - * - * @constructor - * @param{string} key The key associated with this Drawer - */ + renderArea: D3.Selection; + key: string; constructor(key: string); - /** - * Removes the Drawer and its renderArea - */ - public remove(): void; - /** - * Draws the data into the renderArea using the attrHash for attributes - * - * @param{any[][]} data The data to be drawn - * @param{attrHash} IAttributeToProjector The list of attributes to set on the data - */ - public draw(data: any[][], attrToProjector: IAttributeToProjector): void; + remove(): void; + draw(data: any[][], attrToProjector: IAttributeToProjector): void; } } } @@ -1687,8 +629,8 @@ declare module Plottable { declare module Plottable { module _Drawer { - class Rect extends Abstract._Drawer { - public draw(data: any[][], attrToProjector: IAttributeToProjector): void; + class Rect extends Plottable.Abstract._Drawer { + draw(data: any[][], attrToProjector: IAttributeToProjector): void; } } } @@ -1697,138 +639,29 @@ declare module Plottable { declare module Plottable { module Abstract { class Axis extends Component { - /** - * The css class applied to each end tick mark (the line on the end tick). - */ static END_TICK_MARK_CLASS: string; - /** - * The css class applied to each tick mark (the line on the tick). - */ static TICK_MARK_CLASS: string; - /** - * The css class applied to each tick label (the text associated with the tick). - */ static TICK_LABEL_CLASS: string; constructor(scale: Scale, orientation: string, formatter?: (d: any) => string); - public remove(): void; - /** - * Gets the current width. - * - * @returns {number} The current width. - */ - public width(): number; - /** - * Sets a user-specified width. - * - * @param {number|String} w A fixed width for the Axis, or "auto" for automatic mode. - * @returns {Axis} The calling Axis. - */ - public width(w: any): Axis; - /** - * Gets the current height. - * - * @returns {number} The current height. - */ - public height(): number; - /** - * Sets a user-specified height. - * - * @param {number|String} h A fixed height for the Axis, or "auto" for automatic mode. - * @returns {Axis} The calling Axis. - */ - public height(h: any): Axis; - /** - * Get the current formatter on the axis. - * - * @returns {Formatter} the axis formatter - */ - public formatter(): Formatter; - /** - * Sets a new tick formatter. - * - * @param {Formatter} formatter - * @returns {Abstract.Axis} The calling Axis. - */ - public formatter(formatter: Formatter): Axis; - /** - * Gets the current tick mark length. - * - * @returns {number} The current tick mark length. - */ - public tickLength(): number; - /** - * Sets the tick mark length. - * - * @param {number} length The length of each tick. - * @returns {BaseAxis} The calling Axis. - */ - public tickLength(length: number): Axis; - /** - * Gets the current end tick mark length. - * - * @returns {number} The current end tick mark length. - */ - public endTickLength(): number; - /** - * Sets the end tick mark length. - * - * @param {number} length The length of the end ticks. - * @returns {BaseAxis} The calling Axis. - */ - public endTickLength(length: number): Axis; - /** - * Gets the padding between each tick mark and its associated label. - * - * @returns {number} The current padding, in pixels. - */ - public tickLabelPadding(): number; - /** - * Sets the padding between each tick mark and its associated label. - * - * @param {number} padding The desired padding, in pixels. - * @returns {Axis} The calling Axis. - */ - public tickLabelPadding(padding: number): Axis; - /** - * Gets the size of the gutter (the extra space between the tick labels and the outer edge of the axis). - * - * @returns {number} The current size of the gutter, in pixels. - */ - public gutter(): number; - /** - * Sets the size of the gutter (the extra space between the tick labels and the outer edge of the axis). - * - * @param {number} size The desired size of the gutter, in pixels. - * @returns {Axis} The calling Axis. - */ - public gutter(size: number): Axis; - /** - * Gets the orientation of the Axis. - * - * @returns {string} The current orientation. - */ - public orient(): string; - /** - * Sets the orientation of the Axis. - * - * @param {string} newOrientation The desired orientation (top/bottom/left/right). - * @returns {Axis} The calling Axis. - */ - public orient(newOrientation: string): Axis; - /** - * Checks whether the Axis is currently set to show the first and last - * tick labels. - * - * @returns {boolean} - */ - public showEndTickLabels(): boolean; - /** - * Set whether or not to show the first and last tick labels. - * - * @param {boolean} show Whether or not to show the first and last labels. - * @returns {Axis} The calling Axis. - */ - public showEndTickLabels(show: boolean): Axis; + remove(): void; + width(): number; + width(w: any): Axis; + height(): number; + height(h: any): Axis; + formatter(): Formatter; + formatter(formatter: Formatter): Axis; + tickLength(): number; + tickLength(length: number): Axis; + endTickLength(): number; + endTickLength(length: number): Axis; + tickLabelPadding(): number; + tickLabelPadding(padding: number): Axis; + gutter(): number; + gutter(size: number): Axis; + orient(): string; + orient(newOrientation: string): Axis; + showEndTickLabels(): boolean; + showEndTickLabels(show: boolean): Axis; } } } @@ -1841,17 +674,10 @@ declare module Plottable { step: number; formatString: string; } - class Time extends Abstract.Axis { + class Time extends Plottable.Abstract.Axis { static minorIntervals: ITimeInterval[]; static majorIntervals: ITimeInterval[]; - /** - * Creates a TimeAxis - * - * @constructor - * @param {TimeScale} scale The scale to base the Axis on. - * @param {string} orientation The orientation of the Axis (top/bottom) - */ - constructor(scale: Scale.Time, orientation: string); + constructor(scale: Plottable.Scale.Time, orientation: string); } } } @@ -1859,54 +685,12 @@ declare module Plottable { declare module Plottable { module Axis { - class Numeric extends Abstract.Axis { - /** - * Creates a NumericAxis. - * - * @constructor - * @param {QuantitativeScale} scale The QuantitativeScale to base the NumericAxis on. - * @param {string} orientation The orientation of the QuantitativeScale (top/bottom/left/right) - * @param {Formatter} [formatter] A function to format tick labels (default Formatters.general(3, false)). - */ - constructor(scale: Abstract.QuantitativeScale, orientation: string, formatter?: (d: any) => string); - /** - * Gets the tick label position relative to the tick marks. - * - * @returns {string} The current tick label position. - */ - public tickLabelPosition(): string; - /** - * Sets the tick label position relative to the tick marks. - * - * @param {string} position The relative position of the tick label. - * [top/center/bottom] for a vertical NumericAxis, - * [left/center/right] for a horizontal NumericAxis. - * @returns {NumericAxis} The calling NumericAxis. - */ - public tickLabelPosition(position: string): Numeric; - /** - * Return whether or not the tick labels at the end of the graph are - * displayed when partially cut off. - * - * @param {string} orientation Where on the scale to change tick labels. - * On a "top" or "bottom" axis, this can be "left" or - * "right". On a "left" or "right" axis, this can be "top" - * or "bottom". - * @returns {boolean} The current setting. - */ - public showEndTickLabel(orientation: string): boolean; - /** - * Control whether or not the tick labels at the end of the graph are - * displayed when partially cut off. - * - * @param {string} orientation Where on the scale to change tick labels. - * On a "top" or "bottom" axis, this can be "left" or - * "right". On a "left" or "right" axis, this can be "top" - * or "bottom". - * @param {boolean} show Whether or not the given tick should be displayed. - * @returns {Numeric} The calling Numeric. - */ - public showEndTickLabel(orientation: string, show: boolean): Numeric; + class Numeric extends Plottable.Abstract.Axis { + constructor(scale: Plottable.Abstract.QuantitativeScale, orientation: string, formatter?: (d: any) => string); + tickLabelPosition(): string; + tickLabelPosition(position: string): Numeric; + showEndTickLabel(orientation: string): boolean; + showEndTickLabel(orientation: string, show: boolean): Numeric; } } } @@ -1914,19 +698,8 @@ declare module Plottable { declare module Plottable { module Axis { - class Category extends Abstract.Axis { - /** - * Creates a CategoryAxis. - * - * A CategoryAxis takes an OrdinalScale and includes word-wrapping algorithms and advanced layout logic to try to - * display the scale as efficiently as possible. - * - * @constructor - * @param {OrdinalScale} scale The scale to base the Axis on. - * @param {string} orientation The orientation of the Axis (top/bottom/left/right) - * @param {Formatter} [formatter] The Formatter for the Axis (default Formatters.identity()) - */ - constructor(scale: Scale.Ordinal, orientation?: string, formatter?: (d: any) => string); + class Category extends Plottable.Abstract.Axis { + constructor(scale: Plottable.Scale.Ordinal, orientation?: string, formatter?: (d: any) => string); } } } @@ -1934,30 +707,12 @@ declare module Plottable { declare module Plottable { module Component { - class Label extends Abstract.Component { - /** - * Creates a Label. - * - * @constructor - * @param {string} [displayText] The text of the Label. - * @param {string} [orientation] The orientation of the Label (horizontal/vertical-left/vertical-right). - */ + class Label extends Plottable.Abstract.Component { constructor(displayText?: string, orientation?: string); - public xAlign(alignment: string): Label; - public yAlign(alignment: string): Label; - /** - * Retrieve the current text on the Label. - * - * @returns {string} The text on the label. - */ - public text(): string; - /** - * Sets the text on the Label. - * - * @param {string} displayText The new text for the Label. - * @returns {Label} The calling Label. - */ - public text(displayText: string): Label; + xAlign(alignment: string): Label; + yAlign(alignment: string): Label; + text(): string; + text(displayText: string): Label; } class TitleLabel extends Label { constructor(text?: string, orientation?: string); @@ -1977,55 +732,16 @@ declare module Plottable { interface HoverCallback { (datum?: string): any; } - class Legend extends Abstract.Component { - /** - * The css class applied to each legend row - */ + class Legend extends Plottable.Abstract.Component { static SUBELEMENT_CLASS: string; - /** - * Creates a Legend. - * - * A legend consists of a series of legend rows, each with a color and label taken from the `colorScale`. - * The rows will be displayed in the order of the `colorScale` domain. - * This legend also allows interactions, through the functions `toggleCallback` and `hoverCallback` - * Setting a callback will also put classes on the individual rows. - * - * @constructor - * @param {Scale.Color} colorScale - */ - constructor(colorScale?: Scale.Color); - public remove(): void; - /** - * Assigns or gets the callback to the Legend - * - * This callback is associated with toggle events, which trigger when a legend row is clicked. - * Internally, this will change the state of of the row from "toggled-on" to "toggled-off" and vice versa. - * Setting a callback will also set a class to each individual legend row as "toggled-on" or "toggled-off". - * Call with argument of null to remove the callback. This will also remove the above classes to legend rows. - * - * @param {ToggleCallback} callback The new callback function - */ - public toggleCallback(callback: ToggleCallback): Legend; - public toggleCallback(): ToggleCallback; - /** - * Assigns or gets the callback to the Legend - * This callback is associated with hover events, which trigger when the mouse enters or leaves a legend row - * Setting a callback will also set the class "hover" to all legend row, - * as well as the class "focus" to the legend row being hovered over. - * Call with argument of null to remove the callback. This will also remove the above classes to legend rows. - * - * @param{HoverCallback} callback The new callback function - */ - public hoverCallback(callback: HoverCallback): Legend; - public hoverCallback(): HoverCallback; - /** - * Assigns a new ColorScale to the Legend. - * - * @param {ColorScale} scale - * @returns {Legend} The calling Legend. - */ - public scale(scale: Scale.Color): Legend; - public scale(): Scale.Color; + constructor(colorScale?: Plottable.Scale.Color); + remove(): void; + toggleCallback(callback: ToggleCallback): Legend; + toggleCallback(): ToggleCallback; + hoverCallback(callback: HoverCallback): Legend; + hoverCallback(): HoverCallback; + scale(scale: Plottable.Scale.Color): Legend; + scale(): Plottable.Scale.Color; } } } @@ -2033,16 +749,9 @@ declare module Plottable { declare module Plottable { module Component { - class Gridlines extends Abstract.Component { - /** - * Creates a set of Gridlines. - * @constructor - * - * @param {QuantitativeScale} xScale The scale to base the x gridlines on. Pass null if no gridlines are desired. - * @param {QuantitativeScale} yScale The scale to base the y gridlines on. Pass null if no gridlines are desired. - */ - constructor(xScale: Abstract.QuantitativeScale, yScale: Abstract.QuantitativeScale); - public remove(): Gridlines; + class Gridlines extends Plottable.Abstract.Component { + constructor(xScale: Plottable.Abstract.QuantitativeScale, yScale: Plottable.Abstract.QuantitativeScale); + remove(): Gridlines; } } } @@ -2050,17 +759,9 @@ declare module Plottable { declare module Plottable { module Plot { - class Scatter extends Abstract.XYPlot { - /** - * Creates a ScatterPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ - constructor(dataset: any, xScale: Abstract.Scale, yScale: Abstract.Scale); - public project(attrToSet: string, accessor: any, scale?: Abstract.Scale): Scatter; + class Scatter extends Plottable.Abstract.XYPlot { + constructor(dataset: any, xScale: Plottable.Abstract.Scale, yScale: Plottable.Abstract.Scale); + project(attrToSet: string, accessor: any, scale?: Plottable.Abstract.Scale): Scatter; } } } @@ -2068,22 +769,12 @@ declare module Plottable { declare module Plottable { module Plot { - class Grid extends Abstract.XYPlot { - public colorScale: Abstract.Scale; - public xScale: Scale.Ordinal; - public yScale: Scale.Ordinal; - /** - * Creates a GridPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {OrdinalScale} xScale The x scale to use. - * @param {OrdinalScale} yScale The y scale to use. - * @param {ColorScale|InterpolatedColorScale} colorScale The color scale to use for each grid - * cell. - */ - constructor(dataset: any, xScale: Scale.Ordinal, yScale: Scale.Ordinal, colorScale: Abstract.Scale); - public project(attrToSet: string, accessor: any, scale?: Abstract.Scale): Grid; + class Grid extends Plottable.Abstract.XYPlot { + colorScale: Plottable.Abstract.Scale; + xScale: Plottable.Scale.Ordinal; + yScale: Plottable.Scale.Ordinal; + constructor(dataset: any, xScale: Plottable.Scale.Ordinal, yScale: Plottable.Scale.Ordinal, colorScale: Plottable.Abstract.Scale); + project(attrToSet: string, accessor: any, scale?: Plottable.Abstract.Scale): Grid; } } } @@ -2092,51 +783,14 @@ declare module Plottable { declare module Plottable { module Abstract { class BarPlot extends XYPlot { - /** - * Creates an AbstractBarPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ constructor(dataset: any, xScale: Scale, yScale: Scale); - /** - * Sets the baseline for the bars to the specified value. - * - * @param {number} value The value to position the baseline at. - * @return {AbstractBarPlot} The calling AbstractBarPlot. - */ - public baseline(value: number): BarPlot; - /** - * Sets the bar alignment relative to the independent axis. - * VerticalBarPlot supports "left", "center", "right" - * HorizontalBarPlot supports "top", "center", "bottom" - * - * @param {string} alignment The desired alignment. - * @return {AbstractBarPlot} The calling AbstractBarPlot. - */ - public barAlignment(alignment: string): BarPlot; - /** - * Selects the bar under the given pixel position (if [xValOrExtent] - * and [yValOrExtent] are {number}s), under a given line (if only one - * of [xValOrExtent] or [yValOrExtent] are {IExtent}s) or are under a - * 2D area (if [xValOrExtent] and [yValOrExtent] are both {IExtent}s). - * - * @param {any} xValOrExtent The pixel x position, or range of x values. - * @param {any} yValOrExtent The pixel y position, or range of y values. - * @param {boolean} [select] Whether or not to select the bar (by classing it "selected"); - * @return {D3.Selection} The selected bar, or null if no bar was selected. - */ - public selectBar(xValOrExtent: IExtent, yValOrExtent: IExtent, select?: boolean): D3.Selection; - public selectBar(xValOrExtent: number, yValOrExtent: IExtent, select?: boolean): D3.Selection; - public selectBar(xValOrExtent: IExtent, yValOrExtent: number, select?: boolean): D3.Selection; - public selectBar(xValOrExtent: number, yValOrExtent: number, select?: boolean): D3.Selection; - /** - * Deselects all bars. - * @return {AbstractBarPlot} The calling AbstractBarPlot. - */ - public deselectAll(): BarPlot; + baseline(value: number): BarPlot; + barAlignment(alignment: string): BarPlot; + selectBar(xValOrExtent: IExtent, yValOrExtent: IExtent, select?: boolean): D3.Selection; + selectBar(xValOrExtent: number, yValOrExtent: IExtent, select?: boolean): D3.Selection; + selectBar(xValOrExtent: IExtent, yValOrExtent: number, select?: boolean): D3.Selection; + selectBar(xValOrExtent: number, yValOrExtent: number, select?: boolean): D3.Selection; + deselectAll(): BarPlot; } } } @@ -2144,25 +798,8 @@ declare module Plottable { declare module Plottable { module Plot { - /** - * A VerticalBarPlot draws bars vertically. - * Key projected attributes: - * - "width" - the horizontal width of a bar. - * - if an ordinal scale is attached, this defaults to ordinalScale.rangeBand() - * - if a quantitative scale is attached, this defaults to 10 - * - "x" - the horizontal position of a bar - * - "y" - the vertical height of a bar - */ - class VerticalBar extends Abstract.BarPlot { - /** - * Creates a VerticalBarPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {Scale} xScale The x scale to use. - * @param {QuantitativeScale} yScale The y scale to use. - */ - constructor(dataset: any, xScale: Abstract.Scale, yScale: Abstract.QuantitativeScale); + class VerticalBar extends Plottable.Abstract.BarPlot { + constructor(dataset: any, xScale: Plottable.Abstract.Scale, yScale: Plottable.Abstract.QuantitativeScale); } } } @@ -2170,26 +807,9 @@ declare module Plottable { declare module Plottable { module Plot { - /** - * A HorizontalBarPlot draws bars horizontally. - * Key projected attributes: - * - "width" - the vertical height of a bar (since the bar is rotated horizontally) - * - if an ordinal scale is attached, this defaults to ordinalScale.rangeBand() - * - if a quantitative scale is attached, this defaults to 10 - * - "x" - the horizontal length of a bar - * - "y" - the vertical position of a bar - */ - class HorizontalBar extends Abstract.BarPlot { - public isVertical: boolean; - /** - * Creates a HorizontalBarPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {QuantitativeScale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ - constructor(dataset: any, xScale: Abstract.QuantitativeScale, yScale: Abstract.Scale); + class HorizontalBar extends Plottable.Abstract.BarPlot { + isVertical: boolean; + constructor(dataset: any, xScale: Plottable.Abstract.QuantitativeScale, yScale: Plottable.Abstract.Scale); } } } @@ -2197,16 +817,8 @@ declare module Plottable { declare module Plottable { module Plot { - class Line extends Abstract.XYPlot { - /** - * Creates a LinePlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ - constructor(dataset: any, xScale: Abstract.Scale, yScale: Abstract.Scale); + class Line extends Plottable.Abstract.XYPlot { + constructor(dataset: any, xScale: Plottable.Abstract.Scale, yScale: Plottable.Abstract.Scale); } } } @@ -2214,20 +826,9 @@ declare module Plottable { declare module Plottable { module Plot { - /** - * An AreaPlot draws a filled region (area) between the plot's projected "y" and projected "y0" values. - */ class Area extends Line { - /** - * Creates an AreaPlot. - * - * @constructor - * @param {IDataset} dataset The dataset to render. - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ - constructor(dataset: any, xScale: Abstract.Scale, yScale: Abstract.Scale); - public project(attrToSet: string, accessor: any, scale?: Abstract.Scale): Area; + constructor(dataset: any, xScale: Plottable.Abstract.Scale, yScale: Plottable.Abstract.Scale); + project(attrToSet: string, accessor: any, scale?: Plottable.Abstract.Scale): Area; } } } @@ -2237,21 +838,8 @@ declare module Plottable { module Abstract { class NewStyleBarPlot extends NewStylePlot { static DEFAULT_WIDTH: number; - /** - * Creates an NewStyleBarPlot. - * - * @constructor - * @param {Scale} xScale The x scale to use. - * @param {Scale} yScale The y scale to use. - */ constructor(xScale: Scale, yScale: Scale); - /** - * Sets the baseline for the bars to the specified value. - * - * @param {number} value The value to position the baseline at. - * @return {NewStyleBarPlot} The calling NewStyleBarPlot. - */ - public baseline(value: number): any; + baseline(value: number): any; } } } @@ -2259,9 +847,9 @@ declare module Plottable { declare module Plottable { module Plot { - class ClusteredBar extends Abstract.NewStyleBarPlot { + class ClusteredBar extends Plottable.Abstract.NewStyleBarPlot { static DEFAULT_WIDTH: number; - constructor(xScale: Abstract.Scale, yScale: Abstract.QuantitativeScale); + constructor(xScale: Plottable.Abstract.Scale, yScale: Plottable.Abstract.QuantitativeScale); } } } @@ -2269,9 +857,9 @@ declare module Plottable { declare module Plottable { module Plot { - class StackedBar extends Abstract.NewStyleBarPlot { - public stackedData: any[][]; - constructor(xScale?: Abstract.Scale, yScale?: Abstract.Scale); + class StackedBar extends Plottable.Abstract.NewStyleBarPlot { + stackedData: any[][]; + constructor(xScale?: Plottable.Abstract.Scale, yScale?: Plottable.Abstract.Scale); } } } @@ -2279,12 +867,8 @@ declare module Plottable { declare module Plottable { module Animator { - /** - * An animator implementation with no animation. The attributes are - * immediately set on the selection. - */ class Null implements IPlotAnimator { - public animate(selection: any, attrToProjector: IAttributeToProjector, plot: Abstract.Plot): any; + animate(selection: any, attrToProjector: IAttributeToProjector, plot: Plottable.Abstract.Plot): any; } } } @@ -2292,50 +876,14 @@ declare module Plottable { declare module Plottable { module Animator { - /** - * The default animator implementation with easing, duration, and delay. - */ class Default implements IPlotAnimator { - public animate(selection: any, attrToProjector: IAttributeToProjector, plot: Abstract.Plot): any; - /** - * Gets the duration of the animation in milliseconds. - * - * @returns {Number} The current duration. - */ - public duration(): Number; - /** - * Sets the duration of the animation in milliseconds. - * - * @param {Number} duration The duration in milliseconds. - * @returns {Default} The calling Default Animator. - */ - public duration(duration: Number): Default; - /** - * Gets the delay of the animation in milliseconds. - * - * @returns {Number} The current delay. - */ - public delay(): Number; - /** - * Sets the delay of the animation in milliseconds. - * - * @param {Number} delay The delay in milliseconds. - * @returns {Default} The calling Default Animator. - */ - public delay(delay: Number): Default; - /** - * Gets the current easing of the animation. - * - * @returns {string} the current easing mode. - */ - public easing(): string; - /** - * Sets the easing mode of the animation. - * - * @param {string} easing The desired easing mode. - * @returns {Default} The calling Default Animator. - */ - public easing(easing: string): Default; + animate(selection: any, attrToProjector: IAttributeToProjector, plot: Plottable.Abstract.Plot): any; + duration(): Number; + duration(duration: Number): Default; + delay(): Number; + delay(delay: Number): Default; + easing(): string; + easing(easing: string): Default; } } } @@ -2343,14 +891,8 @@ declare module Plottable { declare module Plottable { module Animator { - /** - * An animator that delays the animation of the attributes using the index - * of the selection data. - * - * The delay between animations can be configured with the .delay getter/setter. - */ class IterativeDelay extends Default { - public animate(selection: any, attrToProjector: IAttributeToProjector, plot: Abstract.Plot): any; + animate(selection: any, attrToProjector: IAttributeToProjector, plot: Plottable.Abstract.Plot): any; } } } @@ -2372,20 +914,10 @@ declare module Plottable { declare module Plottable { module Abstract { class Interaction { - public hitBox: D3.Selection; - public componentToListenTo: Component; - /** - * Creates an Interaction. - * - * @constructor - * @param {Component} componentToListenTo The component to listen for interactions on. - */ + hitBox: D3.Selection; + componentToListenTo: Component; constructor(componentToListenTo: Component); - /** - * Registers the Interaction on the Component it's listening to. - * This needs to be called to activate the interaction. - */ - public registerWithComponent(): Interaction; + registerWithComponent(): Interaction; } } } @@ -2393,29 +925,12 @@ declare module Plottable { declare module Plottable { module Interaction { - class Click extends Abstract.Interaction { - /** - * Creates a ClickInteraction. - * - * @constructor - * @param {Component} componentToListenTo The component to listen for clicks on. - */ - constructor(componentToListenTo: Abstract.Component); - /** - * Sets an callback to be called when a click is received. - * - * @param {(x: number, y: number) => any} cb: Callback to be called. Takes click x and y in pixels. - */ - public callback(cb: (x: number, y: number) => any): Click; + class Click extends Plottable.Abstract.Interaction { + constructor(componentToListenTo: Plottable.Abstract.Component); + callback(cb: (x: number, y: number) => any): Click; } class DoubleClick extends Click { - /** - * Creates a DoubleClickInteraction. - * - * @constructor - * @param {Component} componentToListenTo The component to listen for clicks on. - */ - constructor(componentToListenTo: Abstract.Component); + constructor(componentToListenTo: Plottable.Abstract.Component); } } } @@ -2423,9 +938,9 @@ declare module Plottable { declare module Plottable { module Interaction { - class Mousemove extends Abstract.Interaction { - constructor(componentToListenTo: Abstract.Component); - public mousemove(x: number, y: number): void; + class Mousemove extends Plottable.Abstract.Interaction { + constructor(componentToListenTo: Plottable.Abstract.Component); + mousemove(x: number, y: number): void; } } } @@ -2433,21 +948,9 @@ declare module Plottable { declare module Plottable { module Interaction { - class Key extends Abstract.Interaction { - /** - * Creates a KeyInteraction. - * - * @constructor - * @param {Component} componentToListenTo The component to listen for keypresses on. - * @param {number} keyCode The key code to listen for. - */ - constructor(componentToListenTo: Abstract.Component, keyCode: number); - /** - * Sets an callback to be called when the designated key is pressed. - * - * @param {() => any} cb: Callback to be called. - */ - public callback(cb: () => any): Key; + class Key extends Plottable.Abstract.Interaction { + constructor(componentToListenTo: Plottable.Abstract.Component, keyCode: number); + callback(cb: () => any): Key; } } } @@ -2455,19 +958,11 @@ declare module Plottable { declare module Plottable { module Interaction { - class PanZoom extends Abstract.Interaction { - public xScale: Abstract.QuantitativeScale; - public yScale: Abstract.QuantitativeScale; - /** - * Creates a PanZoomInteraction. - * - * @constructor - * @param {Component} componentToListenTo The component to listen for interactions on. - * @param {QuantitativeScale} [xScale] The X scale to update on panning/zooming. - * @param {QuantitativeScale} [yScale] The Y scale to update on panning/zooming. - */ - constructor(componentToListenTo: Abstract.Component, xScale?: Abstract.QuantitativeScale, yScale?: Abstract.QuantitativeScale); - public resetZoom(): void; + class PanZoom extends Plottable.Abstract.Interaction { + xScale: Plottable.Abstract.QuantitativeScale; + yScale: Plottable.Abstract.QuantitativeScale; + constructor(componentToListenTo: Plottable.Abstract.Component, xScale?: Plottable.Abstract.QuantitativeScale, yScale?: Plottable.Abstract.QuantitativeScale); + resetZoom(): void; } } } @@ -2475,47 +970,13 @@ declare module Plottable { declare module Plottable { module Interaction { - class BarHover extends Abstract.Interaction { - public componentToListenTo: Abstract.BarPlot; - /** - * Creates a new BarHover Interaction. - * - * @param {Abstract.BarPlot} barPlot The Bar Plot to listen for hover events on. - */ - constructor(barPlot: Abstract.BarPlot); - /** - * Gets the current hover mode. - * - * @return {string} The current hover mode. - */ - public hoverMode(): string; - /** - * Sets the hover mode for the interaction. There are two modes: - * - "point": Selects the bar under the mouse cursor (default). - * - "line" : Selects any bar that would be hit by a line extending - * in the same direction as the bar and passing through - * the cursor. - * - * @param {string} mode The desired hover mode. - * @return {BarHover} The calling Interaction.BarHover. - */ - public hoverMode(mode: string): BarHover; - /** - * Attaches an callback to be called when the user mouses over a bar. - * - * @param {(datum: any, bar: D3.Selection) => any} The callback to be called. - * The callback will be passed the data from the hovered-over bar. - * @return {BarHover} The calling Interaction.BarHover. - */ - public onHover(callback: (datum: any, bar: D3.Selection) => any): BarHover; - /** - * Attaches a callback to be called when the user mouses off of a bar. - * - * @param {(datum: any, bar: D3.Selection) => any} The callback to be called. - * The callback will be passed the data from the last-hovered bar. - * @return {BarHover} The calling Interaction.BarHover. - */ - public onUnhover(callback: (datum: any, bar: D3.Selection) => any): BarHover; + class BarHover extends Plottable.Abstract.Interaction { + componentToListenTo: Plottable.Abstract.BarPlot; + constructor(barPlot: Plottable.Abstract.BarPlot); + hoverMode(): string; + hoverMode(mode: string): BarHover; + onHover(callback: (datum: any, bar: D3.Selection) => any): BarHover; + onUnhover(callback: (datum: any, bar: D3.Selection) => any): BarHover; } } } @@ -2523,55 +984,17 @@ declare module Plottable { declare module Plottable { module Interaction { - class Drag extends Abstract.Interaction { - public origin: number[]; - public location: number[]; - /** - * Creates a Drag. - * - * @param {Component} componentToListenTo The component to listen for interactions on. - */ - constructor(componentToListenTo: Abstract.Component); - /** - * Gets the callback that is called when dragging starts. - * - * @returns {(startLocation: Point) => void} - */ - public dragstart(): (startLocation: Point) => void; - /** - * Sets the callback to be called when dragging starts. - * - * @param {(startLocation: Point) => any} cb The function to be called. - * @returns {Drag} - */ - public dragstart(cb: (startLocation: Point) => any): Drag; - /** - * Gets the callback that is called during dragging. - * - * @returns {(startLocation: Point, endLocation: Point) => void} - */ - public drag(): (startLocation: Point, endLocation: Point) => void; - /** - * Adds a callback to be called during dragging. - * - * @param {(startLocation: Point, endLocation: Point) => any} cb The function to be called. - * @returns {Drag} - */ - public drag(cb: (startLocation: Point, endLocation: Point) => any): Drag; - /** - * Gets the callback that is called when dragging ends. - * - * @returns {(startLocation: Point, endLocation: Point) => void} - */ - public dragend(): (startLocation: Point, endLocation: Point) => void; - /** - * Adds a callback to be called when the dragging ends. - * - * @param {(startLocation: Point, endLocation: Point) => any} cb The function to be called. Takes in a SelectionArea in pixels. - * @returns {Drag} The calling Drag. - */ - public dragend(cb: (startLocation: Point, endLocation: Point) => any): Drag; - public setupZoomCallback(xScale?: Abstract.QuantitativeScale, yScale?: Abstract.QuantitativeScale): Drag; + class Drag extends Plottable.Abstract.Interaction { + origin: number[]; + location: number[]; + constructor(componentToListenTo: Plottable.Abstract.Component); + dragstart(): (startLocation: Point) => void; + dragstart(cb: (startLocation: Point) => any): Drag; + drag(): (startLocation: Point, endLocation: Point) => void; + drag(cb: (startLocation: Point, endLocation: Point) => any): Drag; + dragend(): (startLocation: Point, endLocation: Point) => void; + dragend(cb: (startLocation: Point, endLocation: Point) => any): Drag; + setupZoomCallback(xScale?: Plottable.Abstract.QuantitativeScale, yScale?: Plottable.Abstract.QuantitativeScale): Drag; } } } @@ -2580,15 +1003,10 @@ declare module Plottable { declare module Plottable { module Interaction { class DragBox extends Drag { - public dragBox: D3.Selection; - public boxIsDrawn: boolean; - /** - * Clears the highlighted drag-selection box drawn by the AreaInteraction. - * - * @returns {AreaInteraction} The calling AreaInteraction. - */ - public clearBox(): DragBox; - public setBox(x0: number, x1: number, y0: number, y1: number): DragBox; + dragBox: D3.Selection; + boxIsDrawn: boolean; + clearBox(): DragBox; + setBox(x0: number, x1: number, y0: number, y1: number): DragBox; } } } @@ -2597,7 +1015,7 @@ declare module Plottable { declare module Plottable { module Interaction { class XDragBox extends DragBox { - public setBox(x0: number, x1: number): XDragBox; + setBox(x0: number, x1: number): XDragBox; } } } @@ -2614,7 +1032,7 @@ declare module Plottable { declare module Plottable { module Interaction { class YDragBox extends DragBox { - public setBox(y0: number, y1: number): YDragBox; + setBox(y0: number, y1: number): YDragBox; } } } @@ -2623,37 +1041,11 @@ declare module Plottable { declare module Plottable { module Abstract { class Dispatcher extends PlottableObject { - /** - * Creates a Dispatcher with the specified target. - * - * @param {D3.Selection} target The selection to listen for events on. - */ constructor(target: D3.Selection); - /** - * Gets the target of the Dispatcher. - * - * @returns {D3.Selection} The Dispatcher's current target. - */ - public target(): D3.Selection; - /** - * Sets the target of the Dispatcher. - * - * @param {D3.Selection} target The element to listen for updates on. - * @returns {Dispatcher} The calling Dispatcher. - */ - public target(targetElement: D3.Selection): Dispatcher; - /** - * Attaches the Dispatcher's listeners to the Dispatcher's target element. - * - * @returns {Dispatcher} The calling Dispatcher. - */ - public connect(): Dispatcher; - /** - * Detaches the Dispatcher's listeners from the Dispatchers' target element. - * - * @returns {Dispatcher} The calling Dispatcher. - */ - public disconnect(): Dispatcher; + target(): D3.Selection; + target(targetElement: D3.Selection): Dispatcher; + connect(): Dispatcher; + disconnect(): Dispatcher; } } } @@ -2661,55 +1053,14 @@ declare module Plottable { declare module Plottable { module Dispatcher { - class Mouse extends Abstract.Dispatcher { - /** - * Creates a Mouse Dispatcher with the specified target. - * - * @param {D3.Selection} target The selection to listen for events on. - */ + class Mouse extends Plottable.Abstract.Dispatcher { constructor(target: D3.Selection); - /** - * Gets the current callback to be called on mouseover. - * - * @return {(location: Point) => any} The current mouseover callback. - */ - public mouseover(): (location: Point) => any; - /** - * Attaches a callback to be called on mouseover. - * - * @param {(location: Point) => any} callback A function that takes the pixel position of the mouse event. - * Pass in null to remove the callback. - * @return {Mouse} The calling Mouse Handler. - */ - public mouseover(callback: (location: Point) => any): Mouse; - /** - * Gets the current callback to be called on mousemove. - * - * @return {(location: Point) => any} The current mousemove callback. - */ - public mousemove(): (location: Point) => any; - /** - * Attaches a callback to be called on mousemove. - * - * @param {(location: Point) => any} callback A function that takes the pixel position of the mouse event. - * Pass in null to remove the callback. - * @return {Mouse} The calling Mouse Handler. - */ - public mousemove(callback: (location: Point) => any): Mouse; - /** - * Gets the current callback to be called on mouseout. - * - * @return {(location: Point) => any} The current mouseout callback. - */ - public mouseout(): (location: Point) => any; - /** - * Attaches a callback to be called on mouseout. - * - * @param {(location: Point) => any} callback A function that takes the pixel position of the mouse event. - * Pass in null to remove the callback. - * @return {Mouse} The calling Mouse Handler. - */ - public mouseout(callback: (location: Point) => any): Mouse; + mouseover(): (location: Point) => any; + mouseover(callback: (location: Point) => any): Mouse; + mousemove(): (location: Point) => any; + mousemove(callback: (location: Point) => any): Mouse; + mouseout(): (location: Point) => any; + mouseout(callback: (location: Point) => any): Mouse; } } } @@ -2717,22 +1068,22 @@ declare module Plottable { declare module Plottable { module Template { - class StandardChart extends Component.Table { + class StandardChart extends Plottable.Component.Table { constructor(); - public yAxis(y: Abstract.Axis): StandardChart; - public yAxis(): Abstract.Axis; - public xAxis(x: Abstract.Axis): StandardChart; - public xAxis(): Abstract.Axis; - public yLabel(y: Component.AxisLabel): StandardChart; - public yLabel(y: string): StandardChart; - public yLabel(): Component.AxisLabel; - public xLabel(x: Component.AxisLabel): StandardChart; - public xLabel(x: string): StandardChart; - public xLabel(): Component.AxisLabel; - public titleLabel(x: Component.TitleLabel): StandardChart; - public titleLabel(x: string): StandardChart; - public titleLabel(): Component.TitleLabel; - public center(c: Abstract.Component): StandardChart; + yAxis(y: Plottable.Abstract.Axis): StandardChart; + yAxis(): Plottable.Abstract.Axis; + xAxis(x: Plottable.Abstract.Axis): StandardChart; + xAxis(): Plottable.Abstract.Axis; + yLabel(y: Plottable.Component.AxisLabel): StandardChart; + yLabel(y: string): StandardChart; + yLabel(): Plottable.Component.AxisLabel; + xLabel(x: Plottable.Component.AxisLabel): StandardChart; + xLabel(x: string): StandardChart; + xLabel(): Plottable.Component.AxisLabel; + titleLabel(x: Plottable.Component.TitleLabel): StandardChart; + titleLabel(x: string): StandardChart; + titleLabel(): Plottable.Component.TitleLabel; + center(c: Plottable.Abstract.Component): StandardChart; } } } diff --git a/test/tests.js b/test/tests.js index a96f4b533e..101dd2fb84 100644 --- a/test/tests.js +++ b/test/tests.js @@ -1,29 +1,26 @@ -/// function generateSVG(width, height) { - if (typeof width === "undefined") { width = 400; } - if (typeof height === "undefined") { height = 400; } + if (width === void 0) { width = 400; } + if (height === void 0) { height = 400; } var parent = getSVGParent(); return parent.append("svg").attr("width", width).attr("height", height).attr("class", "svg"); } - function getSVGParent() { var mocha = d3.select("#mocha-report"); if (mocha.node() != null) { var suites = mocha.selectAll(".suite"); var lastSuite = d3.select(suites[0][suites[0].length - 1]); return lastSuite.selectAll("ul"); - } else { + } + else { return d3.select("body"); } } - function verifySpaceRequest(sr, w, h, ww, wh, id) { assert.equal(sr.width, w, "width requested is as expected #" + id); assert.equal(sr.height, h, "height requested is as expected #" + id); assert.equal(sr.wantsWidth, ww, "needs more width is as expected #" + id); assert.equal(sr.wantsHeight, wh, "needs more height is as expected #" + id); } - function fixComponentSize(c, fixedWidth, fixedHeight) { c._requestedSpace = function (w, h) { return { @@ -37,22 +34,18 @@ function fixComponentSize(c, fixedWidth, fixedHeight) { c._fixedHeightFlag = fixedHeight == null ? false : true; return c; } - function makeFixedSizeComponent(fixedWidth, fixedHeight) { return fixComponentSize(new Plottable.Abstract.Component(), fixedWidth, fixedHeight); } - function getTranslate(element) { return d3.transform(element.attr("transform")).translate; } - function assertBBoxEquivalence(bbox, widthAndHeightPair, message) { var width = widthAndHeightPair[0]; var height = widthAndHeightPair[1]; assert.equal(bbox.width, width, "width: " + message); assert.equal(bbox.height, height, "height: " + message); } - function assertBBoxInclusion(outerEl, innerEl) { var outerBox = outerEl.node().getBoundingClientRect(); var innerBox = innerEl.node().getBoundingClientRect(); @@ -61,35 +54,30 @@ function assertBBoxInclusion(outerEl, innerEl) { assert.operator(Math.ceil(outerBox.right) + window.Pixel_CloseTo_Requirement, ">=", Math.floor(innerBox.right), "bounding rect right included"); assert.operator(Math.ceil(outerBox.bottom) + window.Pixel_CloseTo_Requirement, ">=", Math.floor(innerBox.bottom), "bounding rect bottom included"); } - function assertXY(el, xExpected, yExpected, message) { var x = el.attr("x"); var y = el.attr("y"); assert.equal(x, xExpected, "x: " + message); assert.equal(y, yExpected, "y: " + message); } - function assertWidthHeight(el, widthExpected, heightExpected, message) { var width = el.attr("width"); var height = el.attr("height"); assert.equal(width, widthExpected, "width: " + message); assert.equal(height, heightExpected, "height: " + message); } - function makeLinearSeries(n) { function makePoint(x) { return { x: x, y: x }; } return d3.range(n).map(makePoint); } - function makeQuadraticSeries(n) { function makeQuadraticPoint(x) { return { x: x, y: x * x }; } return d3.range(n).map(makeQuadraticPoint); } - var MultiTestVerifier = (function () { function MultiTestVerifier() { this.passed = true; @@ -98,19 +86,16 @@ var MultiTestVerifier = (function () { this.temp = this.passed; this.passed = false; }; - MultiTestVerifier.prototype.end = function () { this.passed = this.temp; }; return MultiTestVerifier; })(); - function triggerFakeUIEvent(type, target) { var e = document.createEvent("UIEvents"); e.initUIEvent(type, true, true, window, 1); target.node().dispatchEvent(e); } - function triggerFakeMouseEvent(type, target, relativeX, relativeY) { var clientRect = target.node().getBoundingClientRect(); var xPos = clientRect.left + relativeX; @@ -120,14 +105,10 @@ function triggerFakeMouseEvent(type, target, relativeX, relativeY) { target.node().dispatchEvent(e); } -/// - before(function () { - // Set the render policy to immediate to make sure ETE tests can check DOM change immediately Plottable.Core.RenderController.setRenderPolicy(new Plottable.Core.RenderController.RenderPolicy.Immediate()); window.Pixel_CloseTo_Requirement = window.PHANTOMJS ? 2 : 0.5; }); - after(function () { var parent = getSVGParent(); var mocha = d3.select("#mocha-report"); @@ -137,40 +118,28 @@ after(function () { var curSuite = d3.select(suites[0][i]); assert(curSuite.selectAll("ul").selectAll("svg").node() === null, "all svgs have been removed"); } - } else { + } + else { assert(d3.select("body").selectAll("svg").node() === null, "all svgs have been removed"); } }); -/// var assert = chai.assert; - describe("BaseAxis", function () { it("orientation", function () { var scale = new Plottable.Scale.Linear(); - assert.throws(function () { - return new Plottable.Abstract.Axis(scale, "blargh"); - }, "unsupported"); + assert.throws(function () { return new Plottable.Abstract.Axis(scale, "blargh"); }, "unsupported"); }); - it("tickLabelPadding() rejects negative values", function () { var scale = new Plottable.Scale.Linear(); var baseAxis = new Plottable.Abstract.Axis(scale, "bottom"); - - assert.throws(function () { - return baseAxis.tickLabelPadding(-1); - }, "must be positive"); + assert.throws(function () { return baseAxis.tickLabelPadding(-1); }, "must be positive"); }); - it("gutter() rejects negative values", function () { var scale = new Plottable.Scale.Linear(); var axis = new Plottable.Abstract.Axis(scale, "right"); - - assert.throws(function () { - return axis.gutter(-1); - }, "must be positive"); + assert.throws(function () { return axis.gutter(-1); }, "must be positive"); }); - it("width() + gutter()", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 500; @@ -178,35 +147,21 @@ describe("BaseAxis", function () { var scale = new Plottable.Scale.Linear(); var verticalAxis = new Plottable.Abstract.Axis(scale, "right"); verticalAxis.renderTo(svg); - var expectedWidth = verticalAxis.tickLength() + verticalAxis.gutter(); assert.strictEqual(verticalAxis.width(), expectedWidth, "calling width() with no arguments returns currently used width"); - verticalAxis.gutter(20); expectedWidth = verticalAxis.tickLength() + verticalAxis.gutter(); assert.strictEqual(verticalAxis.width(), expectedWidth, "changing the gutter size updates the width"); - verticalAxis.width(20); assert.strictEqual(verticalAxis.width(), 20, "width was set to user-specified value"); - - verticalAxis.width(10 * SVG_WIDTH); // way too big + verticalAxis.width(10 * SVG_WIDTH); assert.strictEqual(verticalAxis.width(), SVG_WIDTH, "returns actual used width if requested width is too large"); - - assert.doesNotThrow(function () { - return verticalAxis.width("auto"); - }, Error, "can be set to auto mode"); - assert.throws(function () { - return verticalAxis.width(-999); - }, Error, "invalid"); - + assert.doesNotThrow(function () { return verticalAxis.width("auto"); }, Error, "can be set to auto mode"); + assert.throws(function () { return verticalAxis.width(-999); }, Error, "invalid"); var horizontalAxis = new Plottable.Abstract.Axis(scale, "bottom"); - assert.throws(function () { - return horizontalAxis.width(2014); - }, Error, "horizontal"); - + assert.throws(function () { return horizontalAxis.width(2014); }, Error, "horizontal"); svg.remove(); }); - it("height() + gutter()", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -214,35 +169,21 @@ describe("BaseAxis", function () { var scale = new Plottable.Scale.Linear(); var horizontalAxis = new Plottable.Abstract.Axis(scale, "bottom"); horizontalAxis.renderTo(svg); - var expectedHeight = horizontalAxis.tickLength() + horizontalAxis.gutter(); assert.strictEqual(horizontalAxis.height(), expectedHeight, "calling height() with no arguments returns currently used height"); - horizontalAxis.gutter(20); expectedHeight = horizontalAxis.tickLength() + horizontalAxis.gutter(); assert.strictEqual(horizontalAxis.height(), expectedHeight, "changing the gutter size updates the height"); - horizontalAxis.height(20); assert.strictEqual(horizontalAxis.height(), 20, "height was set to user-specified value"); - - horizontalAxis.height(10 * SVG_HEIGHT); // way too big + horizontalAxis.height(10 * SVG_HEIGHT); assert.strictEqual(horizontalAxis.height(), SVG_HEIGHT, "returns actual used height if requested height is too large"); - - assert.doesNotThrow(function () { - return horizontalAxis.height("auto"); - }, Error, "can be set to auto mode"); - assert.throws(function () { - return horizontalAxis.height(-999); - }, Error, "invalid"); - + assert.doesNotThrow(function () { return horizontalAxis.height("auto"); }, Error, "can be set to auto mode"); + assert.throws(function () { return horizontalAxis.height(-999); }, Error, "invalid"); var verticalAxis = new Plottable.Abstract.Axis(scale, "right"); - assert.throws(function () { - return verticalAxis.height(2014); - }, Error, "vertical"); - + assert.throws(function () { return verticalAxis.height(2014); }, Error, "vertical"); svg.remove(); }); - it("draws ticks and baseline (horizontal)", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -257,27 +198,22 @@ describe("BaseAxis", function () { return tickValues; }; baseAxis.renderTo(svg); - var tickMarks = svg.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); assert.strictEqual(tickMarks[0].length, tickValues.length, "A tick mark was created for each value"); var baseline = svg.select(".baseline"); - assert.isNotNull(baseline.node(), "baseline was drawn"); assert.strictEqual(baseline.attr("x1"), "0"); assert.strictEqual(baseline.attr("x2"), String(SVG_WIDTH)); assert.strictEqual(baseline.attr("y1"), "0"); assert.strictEqual(baseline.attr("y2"), "0"); - baseAxis.orient("top"); assert.isNotNull(baseline.node(), "baseline was drawn"); assert.strictEqual(baseline.attr("x1"), "0"); assert.strictEqual(baseline.attr("x2"), String(SVG_WIDTH)); assert.strictEqual(baseline.attr("y1"), String(SVG_HEIGHT)); assert.strictEqual(baseline.attr("y2"), String(SVG_HEIGHT)); - svg.remove(); }); - it("draws ticks and baseline (vertical)", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 500; @@ -292,27 +228,22 @@ describe("BaseAxis", function () { return tickValues; }; baseAxis.renderTo(svg); - var tickMarks = svg.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); assert.strictEqual(tickMarks[0].length, tickValues.length, "A tick mark was created for each value"); var baseline = svg.select(".baseline"); - assert.isNotNull(baseline.node(), "baseline was drawn"); assert.strictEqual(baseline.attr("x1"), String(SVG_WIDTH)); assert.strictEqual(baseline.attr("x2"), String(SVG_WIDTH)); assert.strictEqual(baseline.attr("y1"), "0"); assert.strictEqual(baseline.attr("y2"), String(SVG_HEIGHT)); - baseAxis.orient("right"); assert.isNotNull(baseline.node(), "baseline was drawn"); assert.strictEqual(baseline.attr("x1"), "0"); assert.strictEqual(baseline.attr("x2"), "0"); assert.strictEqual(baseline.attr("y1"), "0"); assert.strictEqual(baseline.attr("y2"), String(SVG_HEIGHT)); - svg.remove(); }); - it("tickLength()", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -331,17 +262,11 @@ describe("BaseAxis", function () { assert.strictEqual(secondTickMark.attr("x2"), "50"); assert.strictEqual(secondTickMark.attr("y1"), "0"); assert.strictEqual(secondTickMark.attr("y2"), String(baseAxis.tickLength())); - baseAxis.tickLength(10); assert.strictEqual(secondTickMark.attr("y2"), String(baseAxis.tickLength()), "tick length was updated"); - - assert.throws(function () { - return baseAxis.tickLength(-1); - }, "must be positive"); - + assert.throws(function () { return baseAxis.tickLength(-1); }, "must be positive"); svg.remove(); }); - it("endTickLength()", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -351,27 +276,18 @@ describe("BaseAxis", function () { scale.range([0, SVG_WIDTH]); var baseAxis = new Plottable.Abstract.Axis(scale, "bottom"); var tickValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - baseAxis._getTickValues = function () { - return tickValues; - }; + baseAxis._getTickValues = function () { return tickValues; }; baseAxis.renderTo(svg); - var firstTickMark = svg.selectAll("." + Plottable.Abstract.Axis.END_TICK_MARK_CLASS); assert.strictEqual(firstTickMark.attr("x1"), "0"); assert.strictEqual(firstTickMark.attr("x2"), "0"); assert.strictEqual(firstTickMark.attr("y1"), "0"); assert.strictEqual(firstTickMark.attr("y2"), String(baseAxis.endTickLength())); - baseAxis.endTickLength(10); assert.strictEqual(firstTickMark.attr("y2"), String(baseAxis.endTickLength()), "end tick length was updated"); - - assert.throws(function () { - return baseAxis.endTickLength(-1); - }, "must be positive"); - + assert.throws(function () { return baseAxis.endTickLength(-1); }, "must be positive"); svg.remove(); }); - it("height is adjusted to greater of tickLength or endTickLength", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -380,72 +296,47 @@ describe("BaseAxis", function () { var baseAxis = new Plottable.Abstract.Axis(scale, "bottom"); baseAxis.showEndTickLabels(true); baseAxis.renderTo(svg); - var expectedHeight = Math.max(baseAxis.tickLength(), baseAxis.endTickLength()) + baseAxis.gutter(); assert.strictEqual(baseAxis.height(), expectedHeight, "height should be equal to the maximum of the two"); - baseAxis.tickLength(20); assert.strictEqual(baseAxis.height(), 20 + baseAxis.gutter(), "height should increase to tick length"); - baseAxis.endTickLength(30); assert.strictEqual(baseAxis.height(), 30 + baseAxis.gutter(), "height should increase to end tick length"); - baseAxis.tickLength(10); assert.strictEqual(baseAxis.height(), 30 + baseAxis.gutter(), "height should not decrease"); - svg.remove(); }); }); -/// var assert = chai.assert; - describe("TimeAxis", function () { it("can not initialize vertical time axis", function () { var scale = new Plottable.Scale.Time(); - assert.throws(function () { - return new Plottable.Axis.Time(scale, "left"); - }, "unsupported"); - assert.throws(function () { - return new Plottable.Axis.Time(scale, "right"); - }, "unsupported"); + assert.throws(function () { return new Plottable.Axis.Time(scale, "left"); }, "unsupported"); + assert.throws(function () { return new Plottable.Axis.Time(scale, "right"); }, "unsupported"); }); - it("major and minor intervals arrays are the same length", function () { assert.equal(Plottable.Axis.Time.majorIntervals.length, Plottable.Axis.Time.minorIntervals.length, "major and minor interval arrays must be same size"); }); - it("Computing the default ticks doesn't error out for edge cases", function () { var svg = generateSVG(400, 100); var scale = new Plottable.Scale.Time(); var axis = new Plottable.Axis.Time(scale, "bottom"); scale.range([0, 400]); - - // very large time span - assert.doesNotThrow(function () { - return scale.domain([new Date(0, 0, 1, 0, 0, 0, 0), new Date(50000, 0, 1, 0, 0, 0, 0)]); - }); + assert.doesNotThrow(function () { return scale.domain([new Date(0, 0, 1, 0, 0, 0, 0), new Date(50000, 0, 1, 0, 0, 0, 0)]); }); axis.renderTo(svg); - - // very small time span - assert.doesNotThrow(function () { - return scale.domain([new Date(0, 0, 1, 0, 0, 0, 0), new Date(0, 0, 1, 0, 0, 0, 100)]); - }); + assert.doesNotThrow(function () { return scale.domain([new Date(0, 0, 1, 0, 0, 0, 0), new Date(0, 0, 1, 0, 0, 0, 100)]); }); axis.renderTo(svg); - svg.remove(); }); - it("Tick labels don't overlap", function () { var svg = generateSVG(400, 100); var scale = new Plottable.Scale.Time(); scale.range([0, 400]); var axis = new Plottable.Axis.Time(scale, "bottom"); - function checkDomain(domain) { scale.domain(domain); axis.renderTo(svg); - function checkLabelsForContainer(container) { var visibleTickLabels = container.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS).filter(function (d, i) { return d3.select(this).style("visibility") === "visible"; @@ -457,44 +348,25 @@ describe("TimeAxis", function () { for (var j = i + 1; j < numLabels; j++) { box1 = visibleTickLabels[0][i].getBoundingClientRect(); box2 = visibleTickLabels[0][j].getBoundingClientRect(); - assert.isFalse(Plottable.Util.DOM.boxesOverlap(box1, box2), "tick labels don't overlap"); } } } - checkLabelsForContainer(axis._minorTickLabels); checkLabelsForContainer(axis._majorTickLabels); } - - // 100 year span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2100, 0, 1, 0, 0, 0, 0)]); - - // 1 year span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 11, 31, 0, 0, 0, 0)]); - - // 1 month span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 1, 1, 0, 0, 0, 0)]); - - // 1 day span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 23, 0, 0, 0)]); - - // 1 hour span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 1, 0, 0, 0)]); - - // 1 minute span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 0, 1, 0, 0)]); - - // 1 second span checkDomain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 0, 0, 1, 0)]); - svg.remove(); }); }); -/// var assert = chai.assert; - describe("NumericAxis", function () { function boxesOverlap(boxA, boxB) { if (boxA.right < boxB.left) { @@ -511,9 +383,8 @@ describe("NumericAxis", function () { } return true; } - function boxIsInside(inner, outer, epsilon) { - if (typeof epsilon === "undefined") { epsilon = 0; } + if (epsilon === void 0) { epsilon = 0; } if (inner.left < outer.left - epsilon) { return false; } @@ -528,26 +399,15 @@ describe("NumericAxis", function () { } return true; } - it("tickLabelPosition() input validation", function () { var scale = new Plottable.Scale.Linear(); var horizontalAxis = new Plottable.Axis.Numeric(scale, "bottom"); - assert.throws(function () { - return horizontalAxis.tickLabelPosition("top"); - }, "horizontal"); - assert.throws(function () { - return horizontalAxis.tickLabelPosition("bottom"); - }, "horizontal"); - + assert.throws(function () { return horizontalAxis.tickLabelPosition("top"); }, "horizontal"); + assert.throws(function () { return horizontalAxis.tickLabelPosition("bottom"); }, "horizontal"); var verticalAxis = new Plottable.Axis.Numeric(scale, "left"); - assert.throws(function () { - return verticalAxis.tickLabelPosition("left"); - }, "vertical"); - assert.throws(function () { - return verticalAxis.tickLabelPosition("right"); - }, "vertical"); + assert.throws(function () { return verticalAxis.tickLabelPosition("left"); }, "vertical"); + assert.throws(function () { return verticalAxis.tickLabelPosition("right"); }, "vertical"); }); - it("draws tick labels correctly (horizontal)", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -556,12 +416,10 @@ describe("NumericAxis", function () { scale.range([0, SVG_WIDTH]); var numericAxis = new Plottable.Axis.Numeric(scale, "bottom"); numericAxis.renderTo(svg); - var tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); assert.operator(tickLabels[0].length, ">=", 2, "at least two tick labels were drawn"); var tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); assert.strictEqual(tickLabels[0].length, tickMarks[0].length, "there is one label per mark"); - var i; var markBB; var labelBB; @@ -572,8 +430,6 @@ describe("NumericAxis", function () { var labelCenter = (labelBB.left + labelBB.right) / 2; assert.closeTo(labelCenter, markCenter, 1, "tick label is centered on mark"); } - - // labels to left numericAxis.tickLabelPosition("left"); tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); @@ -582,8 +438,6 @@ describe("NumericAxis", function () { labelBB = tickLabels[0][i].getBoundingClientRect(); assert.operator(labelBB.left, "<=", markBB.right, "tick label is to left of mark"); } - - // labels to right numericAxis.tickLabelPosition("right"); tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); @@ -592,10 +446,8 @@ describe("NumericAxis", function () { labelBB = tickLabels[0][i].getBoundingClientRect(); assert.operator(markBB.right, "<=", labelBB.left, "tick label is to right of mark"); } - svg.remove(); }); - it("draws ticks correctly (vertical)", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 500; @@ -604,12 +456,10 @@ describe("NumericAxis", function () { scale.range([0, SVG_HEIGHT]); var numericAxis = new Plottable.Axis.Numeric(scale, "left"); numericAxis.renderTo(svg); - var tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); assert.operator(tickLabels[0].length, ">=", 2, "at least two tick labels were drawn"); var tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); assert.strictEqual(tickLabels[0].length, tickMarks[0].length, "there is one label per mark"); - var i; var markBB; var labelBB; @@ -620,8 +470,6 @@ describe("NumericAxis", function () { var labelCenter = (labelBB.top + labelBB.bottom) / 2; assert.closeTo(labelCenter, markCenter, 1, "tick label is centered on mark"); } - - // labels to top numericAxis.tickLabelPosition("top"); tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); @@ -630,8 +478,6 @@ describe("NumericAxis", function () { labelBB = tickLabels[0][i].getBoundingClientRect(); assert.operator(labelBB.bottom, "<=", markBB.top, "tick label is above mark"); } - - // labels to bottom numericAxis.tickLabelPosition("bottom"); tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); tickMarks = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS); @@ -640,32 +486,25 @@ describe("NumericAxis", function () { labelBB = tickLabels[0][i].getBoundingClientRect(); assert.operator(markBB.bottom, "<=", labelBB.top, "tick label is below mark"); } - svg.remove(); }); - it("uses the supplied Formatter", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 500; var svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); var scale = new Plottable.Scale.Linear(); scale.range([0, SVG_HEIGHT]); - var formatter = Plottable.Formatters.fixed(2); - var numericAxis = new Plottable.Axis.Numeric(scale, "left", formatter); numericAxis.renderTo(svg); - var tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); tickLabels.each(function (d, i) { var labelText = d3.select(this).text(); var formattedValue = formatter(d); assert.strictEqual(labelText, formattedValue, "The supplied Formatter was used to format the tick label"); }); - svg.remove(); }); - it("can hide tick labels that don't fit", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -673,29 +512,20 @@ describe("NumericAxis", function () { var scale = new Plottable.Scale.Linear(); scale.range([0, SVG_WIDTH]); var numericAxis = new Plottable.Axis.Numeric(scale, "bottom"); - numericAxis.showEndTickLabel("left", false); assert.isFalse(numericAxis.showEndTickLabel("left"), "retrieve showEndTickLabel setting"); numericAxis.showEndTickLabel("right", true); assert.isTrue(numericAxis.showEndTickLabel("right"), "retrieve showEndTickLabel setting"); - assert.throws(function () { - return numericAxis.showEndTickLabel("top", true); - }, Error); - assert.throws(function () { - return numericAxis.showEndTickLabel("bottom", true); - }, Error); - + assert.throws(function () { return numericAxis.showEndTickLabel("top", true); }, Error); + assert.throws(function () { return numericAxis.showEndTickLabel("bottom", true); }, Error); numericAxis.renderTo(svg); - var tickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS); var firstLabel = d3.select(tickLabels[0][0]); assert.strictEqual(firstLabel.style("visibility"), "hidden", "first label is hidden"); var lastLabel = d3.select(tickLabels[0][tickLabels[0].length - 1]); assert.strictEqual(lastLabel.style("visibility"), "hidden", "last label is hidden"); - svg.remove(); }); - it("tick labels don't overlap in a constrained space", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 100; @@ -705,7 +535,6 @@ describe("NumericAxis", function () { var numericAxis = new Plottable.Axis.Numeric(scale, "bottom"); numericAxis.showEndTickLabel("left", false).showEndTickLabel("right", false); numericAxis.renderTo(svg); - var visibleTickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS).filter(function (d, i) { return d3.select(this).style("visibility") === "visible"; }); @@ -716,11 +545,9 @@ describe("NumericAxis", function () { for (var j = i + 1; j < numLabels; j++) { box1 = visibleTickLabels[0][i].getBoundingClientRect(); box2 = visibleTickLabels[0][j].getBoundingClientRect(); - assert.isFalse(Plottable.Util.DOM.boxesOverlap(box1, box2), "tick labels don't overlap"); } } - numericAxis.orient("bottom"); visibleTickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS).filter(function (d, i) { return d3.select(this).style("visibility") === "visible"; @@ -730,14 +557,11 @@ describe("NumericAxis", function () { for (j = i + 1; j < numLabels; j++) { box1 = visibleTickLabels[0][i].getBoundingClientRect(); box2 = visibleTickLabels[0][j].getBoundingClientRect(); - assert.isFalse(Plottable.Util.DOM.boxesOverlap(box1, box2), "tick labels don't overlap"); } } - svg.remove(); }); - it("allocates enough width to show all tick labels when vertical", function () { var SVG_WIDTH = 100; var SVG_HEIGHT = 500; @@ -745,17 +569,14 @@ describe("NumericAxis", function () { var scale = new Plottable.Scale.Linear(); scale.domain([5, -5]); scale.range([0, SVG_HEIGHT]); - var formatter = function (d) { if (d === 0) { return "This is zero"; } return String(d); }; - var numericAxis = new Plottable.Axis.Numeric(scale, "left", formatter); numericAxis.renderTo(svg); - var visibleTickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS).filter(function (d, i) { return d3.select(this).style("visibility") === "visible"; }); @@ -768,7 +589,6 @@ describe("NumericAxis", function () { } svg.remove(); }); - it("allocates enough height to show all tick labels when horizontal", function () { var SVG_WIDTH = 500; var SVG_HEIGHT = 100; @@ -776,12 +596,9 @@ describe("NumericAxis", function () { var scale = new Plottable.Scale.Linear(); scale.domain([5, -5]); scale.range([0, SVG_WIDTH]); - var formatter = Plottable.Formatters.fixed(2); - var numericAxis = new Plottable.Axis.Numeric(scale, "bottom", formatter); numericAxis.renderTo(svg); - var visibleTickLabels = numericAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_LABEL_CLASS).filter(function (d, i) { return d3.select(this).style("visibility") === "visible"; }); @@ -796,7 +613,6 @@ describe("NumericAxis", function () { }); }); -/// var assert = chai.assert; describe("Category Axes", function () { it("re-renders appropriately when data is changed", function () { @@ -805,13 +621,10 @@ describe("Category Axes", function () { var ca = new Plottable.Axis.Category(xScale, "left"); ca.renderTo(svg); assert.deepEqual(ca._tickLabelContainer.selectAll(".tick-label").data(), xScale.domain(), "tick labels render domain"); - assert.doesNotThrow(function () { - return xScale.domain(["bar", "baz", "bam"]); - }); + assert.doesNotThrow(function () { return xScale.domain(["bar", "baz", "bam"]); }); assert.deepEqual(ca._tickLabelContainer.selectAll(".tick-label").data(), xScale.domain(), "tick labels render domain"); svg.remove(); }); - it("requests appropriate space when the scale has no domain", function () { var svg = generateSVG(400, 400); var scale = new Plottable.Scale.Ordinal(); @@ -858,29 +671,23 @@ describe("Category Axes", function () { }); }); -/// var assert = chai.assert; - describe("Gridlines", function () { it("Gridlines and axis tick marks align", function () { var svg = generateSVG(640, 480); var xScale = new Plottable.Scale.Linear(); - xScale.domain([0, 10]); // manually set domain since we won't have a renderer + xScale.domain([0, 10]); var xAxis = new Plottable.Axis.Numeric(xScale, "bottom"); - var yScale = new Plottable.Scale.Linear(); yScale.domain([0, 10]); var yAxis = new Plottable.Axis.Numeric(yScale, "left"); - var gridlines = new Plottable.Component.Gridlines(xScale, yScale); var basicTable = new Plottable.Component.Table().addComponent(0, 0, yAxis).addComponent(0, 1, gridlines).addComponent(1, 1, xAxis); - basicTable._anchor(svg); basicTable._computeLayout(); - xScale.range([0, xAxis.availableWidth]); // manually set range since we don't have a renderer + xScale.range([0, xAxis.availableWidth]); yScale.range([yAxis.availableHeight, 0]); basicTable._render(); - var xAxisTickMarks = xAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS)[0]; var xGridlines = gridlines.element.select(".x-gridlines").selectAll("line")[0]; assert.equal(xAxisTickMarks.length, xGridlines.length, "There is an x gridline for each x tick"); @@ -889,7 +696,6 @@ describe("Gridlines", function () { var xGridlineRect = xGridlines[i].getBoundingClientRect(); assert.closeTo(xTickMarkRect.left, xGridlineRect.left, 1, "x tick and gridline align"); } - var yAxisTickMarks = yAxis.element.selectAll("." + Plottable.Abstract.Axis.TICK_MARK_CLASS)[0]; var yGridlines = gridlines.element.select(".y-gridlines").selectAll("line")[0]; assert.equal(yAxisTickMarks.length, yGridlines.length, "There is an x gridline for each x tick"); @@ -898,40 +704,32 @@ describe("Gridlines", function () { var yGridlineRect = yGridlines[j].getBoundingClientRect(); assert.closeTo(yTickMarkRect.top, yGridlineRect.top, 1, "y tick and gridline align"); } - svg.remove(); }); - it("Unanchored Gridlines don't throw an error when scale updates", function () { var xScale = new Plottable.Scale.Linear(); var gridlines = new Plottable.Component.Gridlines(xScale, null); xScale.domain([0, 1]); - // test passes if error is not thrown. }); }); -/// var assert = chai.assert; - describe("Labels", function () { it("Standard text title label generates properly", function () { var svg = generateSVG(400, 80); var label = new Plottable.Component.TitleLabel("A CHART TITLE"); label.renderTo(svg); - var content = label.content; assert.isTrue(label.element.classed("label"), "title element has label css class"); assert.isTrue(label.element.classed("title-label"), "title element has title-label css class"); var textChildren = content.selectAll("text"); assert.lengthOf(textChildren, 1, "There is one text node in the parent element"); - var text = content.select("text"); var bbox = Plottable.Util.DOM.getBBox(text); assert.closeTo(bbox.height, label.availableHeight, 0.5, "text height === label.minimumHeight()"); assert.equal(text.node().textContent, "A CHART TITLE", "node's text content is as expected"); svg.remove(); }); - it("Left-rotated text is handled properly", function () { var svg = generateSVG(100, 400); var label = new Plottable.Component.AxisLabel("LEFT-ROTATED LABEL", "vertical-left"); @@ -943,7 +741,6 @@ describe("Labels", function () { assert.closeTo(textBBox.height, label.availableWidth, window.Pixel_CloseTo_Requirement, "text height"); svg.remove(); }); - it("Right-rotated text is handled properly", function () { var svg = generateSVG(100, 400); var label = new Plottable.Component.AxisLabel("RIGHT-ROTATED LABEL", "vertical-right"); @@ -955,7 +752,6 @@ describe("Labels", function () { assert.closeTo(textBBox.height, label.availableWidth, window.Pixel_CloseTo_Requirement, "text height"); svg.remove(); }); - it("Label text can be changed after label is created", function () { var svg = generateSVG(400, 80); var label = new Plottable.Component.TitleLabel(); @@ -968,8 +764,6 @@ describe("Labels", function () { assert.operator(label.availableHeight, ">", 0, "rowMin is > 0 for non-empty string"); svg.remove(); }); - - // skipping because Dan is rewriting labels and the height test fails it.skip("Superlong text is handled in a sane fashion", function () { var svgWidth = 400; var svg = generateSVG(svgWidth, 80); @@ -982,7 +776,6 @@ describe("Labels", function () { assert.operator(bbox.width, "<=", svgWidth, "the text is not wider than the SVG width"); svg.remove(); }); - it("text in a tiny box is truncated to empty string", function () { var svg = generateSVG(10, 10); var label = new Plottable.Component.TitleLabel("Yeah, not gonna fit..."); @@ -991,7 +784,6 @@ describe("Labels", function () { assert.equal(text.text(), "", "text was truncated to empty string"); svg.remove(); }); - it("centered text in a table is positioned properly", function () { var svg = generateSVG(400, 400); var label = new Plottable.Component.TitleLabel("X"); @@ -1003,7 +795,6 @@ describe("Labels", function () { assert.closeTo(eleTranslate[0] + textTranslate[0] + textWidth / 2, 200, 5, "label is centered"); svg.remove(); }); - it("if a label text is changed to empty string, width updates to 0", function () { var svg = generateSVG(400, 400); var label = new Plottable.Component.TitleLabel("foo"); @@ -1012,34 +803,26 @@ describe("Labels", function () { assert.equal(label.availableWidth, 0, "width updated to 0"); svg.remove(); }); - it("unsupported alignments and orientations are unsupported", function () { - assert.throws(function () { - return new Plottable.Component.Label("foo", "bar"); - }, Error, "not a valid orientation"); + assert.throws(function () { return new Plottable.Component.Label("foo", "bar"); }, Error, "not a valid orientation"); }); }); -/// var assert = chai.assert; - describe("Legends", function () { var svg; var color; var legend; - beforeEach(function () { svg = generateSVG(400, 400); color = new Plottable.Scale.Color("Category10"); legend = new Plottable.Component.Legend(color); }); - it("a basic legend renders", function () { color.domain(["foo", "bar", "baz"]); legend.renderTo(svg); var rows = legend.content.selectAll(".legend-row"); assert.lengthOf(rows[0], 3, "there are 3 legend entries"); - rows.each(function (d, i) { assert.equal(d, color.domain()[i], "the data is set properly"); var d3this = d3.select(this); @@ -1050,7 +833,6 @@ describe("Legends", function () { }); svg.remove(); }); - it("legend domain can be updated after initialization, and height updates as well", function () { legend.renderTo(svg); legend.scale(color); @@ -1067,20 +849,16 @@ describe("Legends", function () { assert.equal(numRows, 3, "there are 3 rows"); svg.remove(); }); - it("a legend with many labels does not overflow vertically", function () { color.domain(["alpha", "beta", "gamma", "delta", "omega", "omicron", "persei", "eight"]); legend.renderTo(svg); - var contentBBox = Plottable.Util.DOM.getBBox(legend.content); var contentBottomEdge = contentBBox.y + contentBBox.height; var bboxBBox = Plottable.Util.DOM.getBBox(legend.element.select(".bounding-box")); var bboxBottomEdge = bboxBBox.y + bboxBBox.height; - assert.operator(contentBottomEdge, "<=", bboxBottomEdge, "content does not extend past bounding box"); svg.remove(); }); - it("a legend with a long label does not overflow horizontally", function () { color.domain(["foooboooloonoogoorooboopoo"]); svg.attr("width", 100); @@ -1093,7 +871,6 @@ describe("Legends", function () { assert.operator(rightEdge, "<=", rightEdgeBBox, "the long text did not overflow the legend"); svg.remove(); }); - it("calling legend.render multiple times does not add more elements", function () { color.domain(["foo", "bar", "baz"]); legend.renderTo(svg); @@ -1104,14 +881,11 @@ describe("Legends", function () { assert.equal(numRows, 3, "there are 3 legend rows after second render"); svg.remove(); }); - it("re-rendering the legend with a new domain will do the right thing", function () { color.domain(["foo", "bar", "baz"]); legend.renderTo(svg); var newDomain = ["mushu", "foo", "persei", "baz", "eight"]; color.domain(newDomain); - - // due to how joins work, this is how the elements should be arranged by d3 var newDomainActualOrder = ["foo", "baz", "mushu", "persei", "eight"]; legend.content.selectAll(".legend-row").each(function (d, i) { assert.equal(d, newDomainActualOrder[i], "the data is set correctly"); @@ -1123,16 +897,13 @@ describe("Legends", function () { assert.lengthOf(legend.content.selectAll(".legend-row")[0], 5, "there are the right number of legend elements"); svg.remove(); }); - it("legend.scale() replaces domain", function () { color.domain(["foo", "bar", "baz"]); legend.renderTo(svg); - var newDomain = ["a", "b", "c"]; var newColorScale = new Plottable.Scale.Color("20"); newColorScale.domain(newDomain); legend.scale(newColorScale); - legend.content.selectAll(".legend-row").each(function (d, i) { assert.equal(d, newDomain[i], "the data is set correctly"); var text = d3.select(this).select("text").text(); @@ -1140,19 +911,15 @@ describe("Legends", function () { var fill = d3.select(this).select("circle").attr("fill"); assert.equal(fill, newColorScale.scale(d), "the fill was set properly"); }); - svg.remove(); }); - it("legend.scale() correctly reregisters listeners", function () { color.domain(["foo", "bar", "baz"]); legend.renderTo(svg); - var tempDomain = ["a", "b", "c"]; var newColorScale = new Plottable.Scale.Color("20"); newColorScale.domain(tempDomain); legend.scale(newColorScale); - var newDomain = ["a", "foo", "d"]; newColorScale.domain(newDomain); legend.content.selectAll(".legend-row").each(function (d, i) { @@ -1164,13 +931,11 @@ describe("Legends", function () { }); svg.remove(); }); - it("icon radius is not too small or too big", function () { color.domain(["foo"]); legend.renderTo(svg); var style = legend.element.append("style"); style.attr("type", "text/css"); - function verifyCircleHeight() { var text = legend.content.select("text"); var circle = legend.content.select("circle"); @@ -1179,51 +944,38 @@ describe("Legends", function () { assert.operator(circleHeight, "<", textHeight, "icons are too big. iconHeight = " + circleHeight + " vs circleHeight = " + circleHeight); assert.operator(circleHeight, ">", textHeight / 2, "icons are too small. iconHeight = " + circleHeight + " vs circleHeight = " + circleHeight); } - verifyCircleHeight(); - style.text(".plottable .legend text { font-size: 60px; }"); legend._computeLayout(); legend._render(); verifyCircleHeight(); - style.text(".plottable .legend text { font-size: 10px; }"); legend._computeLayout(); legend._render(); verifyCircleHeight(); - svg.remove(); }); - describe("Legend toggle tests", function () { var toggleLegend; - beforeEach(function () { toggleLegend = new Plottable.Component.Legend(color); toggleLegend.toggleCallback(function (d, b) { }); }); - function verifyState(selection, b, msg) { assert.equal(selection.classed("toggled-on"), b, msg); assert.equal(selection.classed("toggled-off"), !b, msg); } - function getSelection(datum) { - var selection = toggleLegend.content.selectAll(".legend-row").filter(function (d, i) { - return d === datum; - }); + var selection = toggleLegend.content.selectAll(".legend-row").filter(function (d, i) { return d === datum; }); return selection; } - function verifyEntry(datum, b, msg) { verifyState(getSelection(datum), b, msg); } - function toggleEntry(datum, index) { getSelection(datum).on("click")(datum, index); } - it("basic initialization test", function () { color.domain(["a", "b", "c", "d", "e"]); toggleLegend.renderTo(svg); @@ -1233,7 +985,6 @@ describe("Legends", function () { }); svg.remove(); }); - it("basic toggling test", function () { color.domain(["a"]); toggleLegend.renderTo(svg); @@ -1246,7 +997,6 @@ describe("Legends", function () { }); svg.remove(); }); - it("scale() works as intended with toggling", function () { var domain = ["a", "b", "c", "d", "e"]; color.domain(domain); @@ -1254,27 +1004,22 @@ describe("Legends", function () { toggleEntry("a", 0); toggleEntry("d", 3); toggleEntry("c", 2); - var newDomain = ["r", "a", "d", "g"]; var newColorScale = new Plottable.Scale.Color("Category10"); newColorScale.domain(newDomain); toggleLegend.scale(newColorScale); - verifyEntry("r", true); verifyEntry("a", false); verifyEntry("g", true); verifyEntry("d", false); - svg.remove(); }); - it("listeners on scale will correctly update states", function () { color.domain(["a", "b", "c", "d", "e"]); toggleLegend.renderTo(svg); toggleEntry("a", 0); toggleEntry("d", 3); toggleEntry("c", 2); - color.domain(["e", "d", "b", "a", "c"]); verifyEntry("a", false); verifyEntry("b", true); @@ -1283,132 +1028,101 @@ describe("Legends", function () { verifyEntry("e", true); svg.remove(); }); - it("Testing callback works correctly", function () { var domain = ["a", "b", "c", "d", "e"]; color.domain(domain); var state = [true, true, true, true, true]; - toggleLegend.toggleCallback(function (d, b) { state[domain.indexOf(d)] = b; }); toggleLegend.renderTo(svg); - toggleEntry("a", 0); verifyEntry("a", false); assert.equal(state[0], false, "callback was successful"); - toggleEntry("d", 3); verifyEntry("d", false); assert.equal(state[3], false, "callback was successful"); - toggleEntry("a", 0); verifyEntry("a", true); assert.equal(state[0], true, "callback was successful"); - toggleEntry("c", 2); verifyEntry("c", false); assert.equal(state[2], false, "callback was successful"); svg.remove(); }); - it("Overwriting callback is successfull", function () { var domain = ["a"]; color.domain(domain); var state = true; toggleLegend.renderTo(svg); - toggleLegend.toggleCallback(function (d, b) { state = b; }); - toggleEntry("a", 0); assert.equal(state, false, "callback was successful"); - var count = 0; toggleLegend.toggleCallback(function (d, b) { count++; }); - toggleEntry("a", 0); assert.equal(state, false, "callback was overwritten"); assert.equal(count, 1, "new callback was successfully called"); svg.remove(); }); - it("Removing callback is successful", function () { var domain = ["a"]; color.domain(domain); var state = true; toggleLegend.renderTo(svg); - toggleLegend.toggleCallback(function (d, b) { state = b; }); - toggleEntry("a", 0); assert.equal(state, false, "callback was successful"); - - toggleLegend.toggleCallback(); // this should not remove the callback + toggleLegend.toggleCallback(); toggleEntry("a", 0); assert.equal(state, true, "callback was successful"); - - toggleLegend.toggleCallback(null); // this should remove the callback + toggleLegend.toggleCallback(null); assert.throws(function () { toggleEntry("a", 0); }); var selection = getSelection("a"); - - // should have no classes assert.equal(selection.classed("toggled-on"), false, "is not toggled-on"); assert.equal(selection.classed("toggled-off"), false, "is not toggled-off"); - svg.remove(); }); }); - describe("Legend hover tests", function () { var hoverLegend; - beforeEach(function () { hoverLegend = new Plottable.Component.Legend(color); hoverLegend.hoverCallback(function (d) { }); }); - function _verifyFocus(selection, b, msg) { assert.equal(selection.classed("hover"), true, msg); assert.equal(selection.classed("focus"), b, msg); } - function _verifyEmpty(selection, msg) { assert.equal(selection.classed("hover"), false, msg); assert.equal(selection.classed("focus"), false, msg); } - function getSelection(datum) { - var selection = hoverLegend.content.selectAll(".legend-row").filter(function (d, i) { - return d === datum; - }); + var selection = hoverLegend.content.selectAll(".legend-row").filter(function (d, i) { return d === datum; }); return selection; } - function verifyFocus(datum, b, msg) { _verifyFocus(getSelection(datum), b, msg); } - function verifyEmpty(datum, msg) { _verifyEmpty(getSelection(datum), msg); } - function hoverEntry(datum, index) { getSelection(datum).on("mouseover")(datum, index); } - function leaveEntry(datum, index) { getSelection(datum).on("mouseout")(datum, index); } - it("basic initialization test", function () { color.domain(["a", "b", "c", "d", "e"]); hoverLegend.renderTo(svg); @@ -1417,7 +1131,6 @@ describe("Legends", function () { }); svg.remove(); }); - it("basic hover test", function () { color.domain(["a"]); hoverLegend.renderTo(svg); @@ -1427,38 +1140,30 @@ describe("Legends", function () { verifyEmpty("a"); svg.remove(); }); - it("scale() works as intended with hovering", function () { var domain = ["a", "b", "c", "d", "e"]; color.domain(domain); hoverLegend.renderTo(svg); - hoverEntry("a", 0); - var newDomain = ["r", "a", "d", "g"]; var newColorScale = new Plottable.Scale.Color("Category10"); newColorScale.domain(newDomain); hoverLegend.scale(newColorScale); - verifyFocus("r", false, "r"); verifyFocus("a", true, "a"); verifyFocus("g", false, "g"); verifyFocus("d", false, "d"); - leaveEntry("a", 0); verifyEmpty("r"); verifyEmpty("a"); verifyEmpty("g"); verifyEmpty("d"); - svg.remove(); }); - it("listeners on scale will correctly update states", function () { color.domain(["a", "b", "c", "d", "e"]); hoverLegend.renderTo(svg); hoverEntry("c", 2); - color.domain(["e", "d", "b", "a", "c"]); verifyFocus("a", false); verifyFocus("b", false); @@ -1467,49 +1172,39 @@ describe("Legends", function () { verifyFocus("e", false); svg.remove(); }); - it("Testing callback works correctly", function () { var domain = ["a", "b", "c", "d", "e"]; color.domain(domain); var focused = undefined; - hoverLegend.hoverCallback(function (d) { focused = d; }); hoverLegend.renderTo(svg); - hoverEntry("a", 0); verifyFocus("a", true); assert.equal(focused, "a", "callback was successful"); - leaveEntry("a", 0); assert.equal(focused, undefined, "callback was successful"); - hoverEntry("d", 3); verifyFocus("d", true); assert.equal(focused, "d", "callback was successful"); svg.remove(); }); - it("Overwriting callback is successfull", function () { var domain = ["a"]; color.domain(domain); var focused = undefined; hoverLegend.renderTo(svg); - hoverLegend.hoverCallback(function (d) { focused = d; }); - hoverEntry("a", 0); assert.equal(focused, "a", "callback was successful"); leaveEntry("a", 0); - var count = 0; hoverLegend.hoverCallback(function (d) { count++; }); - hoverEntry("a", 0); assert.equal(focused, undefined, "old callback was not called"); assert.equal(count, 1, "new callbcak was called"); @@ -1517,36 +1212,29 @@ describe("Legends", function () { assert.equal(count, 2, "new callback was called"); svg.remove(); }); - it("Removing callback is successful", function () { var domain = ["a"]; color.domain(domain); var focused = undefined; hoverLegend.renderTo(svg); - hoverLegend.hoverCallback(function (d) { focused = d; }); - hoverEntry("a", 0); assert.equal(focused, "a", "callback was successful"); - - hoverLegend.hoverCallback(); // this should not remove the callback + hoverLegend.hoverCallback(); leaveEntry("a", 0); assert.equal(focused, undefined, "callback was successful"); - - hoverLegend.hoverCallback(null); // this should remove the callback + hoverLegend.hoverCallback(null); assert.throws(function () { hoverEntry("a", 0); }); verifyEmpty("a"); - svg.remove(); }); }); }); -/// var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } @@ -1566,14 +1254,12 @@ var CountingPlot = (function (_super) { }; return CountingPlot; })(Plottable.Abstract.Plot); - describe("Plots", function () { describe("Abstract Plot", function () { it("Plots default correctly", function () { var r = new Plottable.Abstract.Plot(); assert.isTrue(r.clipPathEnabled, "clipPathEnabled defaults to true"); }); - it("Base Plot functionality works", function () { var svg = generateSVG(400, 300); var d1 = new Plottable.DataSource(["foo"], { cssClass: "bar" }); @@ -1584,51 +1270,38 @@ describe("Plots", function () { assert.isNotNull(renderArea.node(), "there is a render-area"); svg.remove(); }); - it("Allows the DataSource to be changed", function () { var d1 = new Plottable.DataSource(["foo"], { cssClass: "bar" }); var r = new Plottable.Abstract.Plot(d1); assert.equal(d1, r.dataSource(), "returns the original"); - var d2 = new Plottable.DataSource(["bar"], { cssClass: "boo" }); r.dataSource(d2); assert.equal(d2, r.dataSource(), "returns new datasource"); }); - it("Changes DataSource listeners when the DataSource is changed", function () { var d1 = new Plottable.DataSource(["foo"], { cssClass: "bar" }); var r = new CountingPlot(d1); - assert.equal(0, r.renders, "initially hasn't rendered anything"); - d1.broadcaster.broadcast(); assert.equal(1, r.renders, "we re-render when our datasource changes"); - r.dataSource(); assert.equal(1, r.renders, "we shouldn't redraw when querying the datasource"); - var d2 = new Plottable.DataSource(["bar"], { cssClass: "boo" }); r.dataSource(d2); assert.equal(2, r.renders, "we should redraw when we change datasource"); - d1.broadcaster.broadcast(); assert.equal(2, r.renders, "we shouldn't listen to the old datasource"); - d2.broadcaster.broadcast(); assert.equal(3, r.renders, "we should listen to the new datasource"); }); - it("Updates its projectors when the DataSource is changed", function () { var d1 = new Plottable.DataSource([{ x: 5, y: 6 }], { cssClass: "bar" }); var r = new Plottable.Abstract.Plot(d1); - var xScaleCalls = 0; var yScaleCalls = 0; var xScale = new Plottable.Scale.Linear(); var yScale = new Plottable.Scale.Linear(); - var metadataProjector = function (d, i, m) { - return m.cssClass; - }; + var metadataProjector = function (d, i, m) { return m.cssClass; }; r.project("x", "x", xScale); r.project("y", "y", yScale); r.project("meta", metadataProjector); @@ -1640,34 +1313,26 @@ describe("Plots", function () { assert.equal(listenable, yScale, "Callback received the calling scale as the first argument"); ++yScaleCalls; }); - assert.equal(0, xScaleCalls, "initially hasn't made any X callbacks"); assert.equal(0, yScaleCalls, "initially hasn't made any Y callbacks"); - d1.broadcaster.broadcast(); assert.equal(1, xScaleCalls, "X scale was wired up to datasource correctly"); assert.equal(1, yScaleCalls, "Y scale was wired up to datasource correctly"); - var metaProjector = r._generateAttrToProjector()["meta"]; assert.equal(metaProjector(null, 0), "bar", "plot projector used the right metadata"); - var d2 = new Plottable.DataSource([{ x: 7, y: 8 }], { cssClass: "boo" }); r.dataSource(d2); assert.equal(2, xScaleCalls, "Changing datasource fires X scale listeners (but doesn't coalesce callbacks)"); assert.equal(2, yScaleCalls, "Changing datasource fires Y scale listeners (but doesn't coalesce callbacks)"); - d1.broadcaster.broadcast(); assert.equal(2, xScaleCalls, "X scale was unhooked from old datasource"); assert.equal(2, yScaleCalls, "Y scale was unhooked from old datasource"); - d2.broadcaster.broadcast(); assert.equal(3, xScaleCalls, "X scale was hooked into new datasource"); assert.equal(3, yScaleCalls, "Y scale was hooked into new datasource"); - metaProjector = r._generateAttrToProjector()["meta"]; assert.equal(metaProjector(null, 0), "boo", "plot projector used the right metadata"); }); - it("Plot automatically generates a DataSource if only data is provided", function () { var data = ["foo", "bar"]; var r = new Plottable.Abstract.Plot(data); @@ -1675,7 +1340,6 @@ describe("Plots", function () { assert.isNotNull(dataSource, "A DataSource was automatically generated"); assert.deepEqual(dataSource.data(), data, "The generated DataSource has the correct data"); }); - it("Plot.project works as intended", function () { var r = new Plottable.Abstract.Plot(); var s = new Plottable.Scale.Linear().domain([0, 1]).range([0, 10]); @@ -1684,26 +1348,20 @@ describe("Plots", function () { var projector = attrToProjector["attr"]; assert.equal(projector({ "a": 0.5 }, 0), 5, "projector works as intended"); }); - it("Changing Plot.dataSource().data to [] causes scale to contract", function () { var ds1 = new Plottable.DataSource([0, 1, 2]); var ds2 = new Plottable.DataSource([1, 2, 3]); var s = new Plottable.Scale.Linear(); var svg1 = generateSVG(100, 100); var svg2 = generateSVG(100, 100); - var r1 = new Plottable.Abstract.Plot().dataSource(ds1).project("x", function (x) { - return x; - }, s).renderTo(svg1); - var r2 = new Plottable.Abstract.Plot().dataSource(ds2).project("x", function (x) { - return x; - }, s).renderTo(svg2); + var r1 = new Plottable.Abstract.Plot().dataSource(ds1).project("x", function (x) { return x; }, s).renderTo(svg1); + var r2 = new Plottable.Abstract.Plot().dataSource(ds2).project("x", function (x) { return x; }, s).renderTo(svg2); assert.deepEqual(s.domain(), [0, 3], "Simple domain combining"); ds1.data([]); assert.deepEqual(s.domain(), [1, 3], "Contracting domain due to projection becoming empty"); svg1.remove(); svg2.remove(); }); - it("remove() disconnects plots from its scales", function () { var r = new Plottable.Abstract.Plot(); var s = new Plottable.Scale.Linear(); @@ -1715,26 +1373,20 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; describe("Plots", function () { describe("New Style Plots", function () { var p; var oldWarn = Plottable.Util.Methods.warn; - beforeEach(function () { var xScale = new Plottable.Scale.Linear(); var yScale = new Plottable.Scale.Linear(); p = new Plottable.Abstract.NewStylePlot(xScale, yScale); - p._getDrawer = function (k) { - return new Plottable._Drawer.Rect(k); - }; + p._getDrawer = function (k) { return new Plottable._Drawer.Rect(k); }; }); - afterEach(function () { Plottable.Util.Methods.warn = oldWarn; }); - it("Datasets can be added and removed as expected", function () { p.addDataset("foo", [1, 2, 3]); var d2 = new Plottable.DataSource([4, 5, 6]); @@ -1742,26 +1394,20 @@ describe("Plots", function () { p.addDataset([7, 8, 9]); var d4 = new Plottable.DataSource([10, 11, 12]); p.addDataset(d4); - assert.deepEqual(p._datasetKeysInOrder, ["foo", "bar", "_0", "_1"], "dataset keys as expected"); var datasets = p._getDatasetsInOrder(); assert.deepEqual(datasets[0].data(), [1, 2, 3]); assert.equal(datasets[1], d2); assert.deepEqual(datasets[2].data(), [7, 8, 9]); assert.equal(datasets[3], d4); - p.removeDataset("foo"); p.removeDataset("_0"); - assert.deepEqual(p._datasetKeysInOrder, ["bar", "_1"]); assert.lengthOf(p._getDatasetsInOrder(), 2); }); - it("Datasets are listened to appropriately", function () { var callbackCounter = 0; - var callback = function () { - return callbackCounter++; - }; + var callback = function () { return callbackCounter++; }; p._onDataSourceUpdate = callback; var d = new Plottable.DataSource([1, 2, 3]); p.addDataset("foo", d); @@ -1771,7 +1417,6 @@ describe("Plots", function () { p.removeDataset("foo"); assert.equal(callbackCounter, 3, "removing dataset triggers listener"); }); - it("Datasets can be reordered", function () { p.addDataset("foo", [1]); p.addDataset("bar", [2]); @@ -1780,38 +1425,27 @@ describe("Plots", function () { p.datasetOrder(["bar", "baz", "foo"]); assert.deepEqual(p.datasetOrder(), ["bar", "baz", "foo"]); var warned = 0; - Plottable.Util.Methods.warn = function () { - return warned++; - }; // suppress expected warnings + Plottable.Util.Methods.warn = function () { return warned++; }; p.datasetOrder(["blah", "blee", "bar", "baz", "foo"]); assert.equal(warned, 1); assert.deepEqual(p.datasetOrder(), ["bar", "baz", "foo"]); }); - it("Has proper warnings", function () { var warned = 0; - Plottable.Util.Methods.warn = function () { - return warned++; - }; + Plottable.Util.Methods.warn = function () { return warned++; }; p.addDataset("_foo", []); assert.equal(warned, 1); p.addDataset("2", []); p.addDataset("4", []); - - // get warning for not a permutation p.datasetOrder(["_bar", "4", "2"]); assert.equal(warned, 2); - - // do not get warning for a permutation p.datasetOrder(["2", "_foo", "4"]); assert.equal(warned, 2); }); }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("LinePlot", function () { var svg; @@ -1824,36 +1458,23 @@ describe("Plots", function () { var linePlot; var renderArea; var verifier; - - // for IE, whose paths look like "M 0 500 L" instead of "M0,500L" - var normalizePath = function (s) { - return s.replace(/ *([A-Z]) */g, "$1").replace(/ /g, ","); - }; - + var normalizePath = function (s) { return s.replace(/ *([A-Z]) */g, "$1").replace(/ /g, ","); }; before(function () { svg = generateSVG(500, 500); verifier = new MultiTestVerifier(); xScale = new Plottable.Scale.Linear().domain([0, 1]); yScale = new Plottable.Scale.Linear().domain([0, 1]); - xAccessor = function (d) { - return d.foo; - }; - yAccessor = function (d) { - return d.bar; - }; - colorAccessor = function (d, i, m) { - return d3.rgb(d.foo, d.bar, i).toString(); - }; + xAccessor = function (d) { return d.foo; }; + yAccessor = function (d) { return d.bar; }; + colorAccessor = function (d, i, m) { return d3.rgb(d.foo, d.bar, i).toString(); }; simpleDataset = new Plottable.DataSource([{ foo: 0, bar: 0 }, { foo: 1, bar: 1 }]); linePlot = new Plottable.Plot.Line(simpleDataset, xScale, yScale); linePlot.project("x", xAccessor, xScale).project("y", yAccessor, yScale).project("stroke", colorAccessor).renderTo(svg); renderArea = linePlot.renderArea; }); - beforeEach(function () { verifier.start(); }); - it("draws a line correctly", function () { var linePath = renderArea.select(".line"); assert.strictEqual(normalizePath(linePath.attr("d")), "M0,500L500,0", "line d was set correctly"); @@ -1861,24 +1482,19 @@ describe("Plots", function () { assert.strictEqual(lineComputedStyle.fill, "none", "line fill renders as \"none\""); verifier.end(); }); - it("attributes set appropriately from accessor", function () { var areaPath = renderArea.select(".line"); assert.equal(areaPath.attr("stroke"), "#000000", "stroke set correctly"); verifier.end(); }); - it("attributes can be changed by projecting new accessor and re-render appropriately", function () { - var newColorAccessor = function () { - return "pink"; - }; + var newColorAccessor = function () { return "pink"; }; linePlot.project("stroke", newColorAccessor); linePlot.renderTo(svg); var linePath = renderArea.select(".line"); assert.equal(linePath.attr("stroke"), "pink", "stroke changed correctly"); verifier.end(); }); - it("attributes can be changed by projecting attribute accessor (sets to first datum attribute)", function () { var data = simpleDataset.data(); data.forEach(function (d) { @@ -1888,13 +1504,11 @@ describe("Plots", function () { linePlot.project("stroke", "stroke"); var areaPath = renderArea.select(".line"); assert.equal(areaPath.attr("stroke"), "pink", "stroke set to uniform stroke color"); - data[0].stroke = "green"; simpleDataset.data(data); assert.equal(areaPath.attr("stroke"), "green", "stroke set to first datum stroke color"); verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); @@ -1904,9 +1518,7 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("AreaPlot", function () { var svg; @@ -1921,49 +1533,31 @@ describe("Plots", function () { var areaPlot; var renderArea; var verifier; - - // for IE, whose paths look like "M 0 500 L" instead of "M0,500L" - var normalizePath = function (s) { - return s.replace(/ *([A-Z]) */g, "$1").replace(/ /g, ","); - }; - + var normalizePath = function (s) { return s.replace(/ *([A-Z]) */g, "$1").replace(/ /g, ","); }; before(function () { svg = generateSVG(500, 500); verifier = new MultiTestVerifier(); xScale = new Plottable.Scale.Linear().domain([0, 1]); yScale = new Plottable.Scale.Linear().domain([0, 1]); - xAccessor = function (d) { - return d.foo; - }; - yAccessor = function (d) { - return d.bar; - }; - y0Accessor = function () { - return 0; - }; - colorAccessor = function (d, i, m) { - return d3.rgb(d.foo, d.bar, i).toString(); - }; - fillAccessor = function () { - return "steelblue"; - }; + xAccessor = function (d) { return d.foo; }; + yAccessor = function (d) { return d.bar; }; + y0Accessor = function () { return 0; }; + colorAccessor = function (d, i, m) { return d3.rgb(d.foo, d.bar, i).toString(); }; + fillAccessor = function () { return "steelblue"; }; simpleDataset = new Plottable.DataSource([{ foo: 0, bar: 0 }, { foo: 1, bar: 1 }]); areaPlot = new Plottable.Plot.Area(simpleDataset, xScale, yScale); areaPlot.project("x", xAccessor, xScale).project("y", yAccessor, yScale).project("y0", y0Accessor, yScale).project("fill", fillAccessor).project("stroke", colorAccessor).renderTo(svg); renderArea = areaPlot.renderArea; }); - beforeEach(function () { verifier.start(); }); - it("draws area and line correctly", function () { var areaPath = renderArea.select(".area"); assert.strictEqual(normalizePath(areaPath.attr("d")), "M0,500L500,0L500,500L0,500Z", "area d was set correctly"); assert.strictEqual(areaPath.attr("fill"), "steelblue", "area fill was set correctly"); var areaComputedStyle = window.getComputedStyle(areaPath.node()); assert.strictEqual(areaComputedStyle.stroke, "none", "area stroke renders as \"none\""); - var linePath = renderArea.select(".line"); assert.strictEqual(normalizePath(linePath.attr("d")), "M0,500L500,0", "line d was set correctly"); assert.strictEqual(linePath.attr("stroke"), "#000000", "line stroke was set correctly"); @@ -1971,18 +1565,14 @@ describe("Plots", function () { assert.strictEqual(lineComputedStyle.fill, "none", "line fill renders as \"none\""); verifier.end(); }); - it("area fill works for non-zero floor values appropriately, e.g. half the height of the line", function () { - areaPlot.project("y0", function (d) { - return d.bar / 2; - }, yScale); + areaPlot.project("y0", function (d) { return d.bar / 2; }, yScale); areaPlot.renderTo(svg); renderArea = areaPlot.renderArea; var areaPath = renderArea.select(".area"); assert.equal(normalizePath(areaPath.attr("d")), "M0,500L500,0L500,250L0,500Z"); verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); @@ -1992,9 +1582,7 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("Bar Plot", function () { describe("Vertical Bar Plot in points mode", function () { @@ -2006,7 +1594,6 @@ describe("Plots", function () { var renderer; var SVG_WIDTH = 600; var SVG_HEIGHT = 400; - before(function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); xScale = new Plottable.Scale.Ordinal().domain(["A", "B"]).rangeType("points"); @@ -2017,18 +1604,15 @@ describe("Plots", function () { { x: "B", y: 1 } ]; dataset = new Plottable.DataSource(data); - renderer = new Plottable.Plot.VerticalBar(dataset, xScale, yScale); renderer.animate(false); renderer.renderTo(svg); }); - beforeEach(function () { yScale.domain([-2, 2]); renderer.baseline(0); verifier.start(); }); - it("renders correctly", function () { var renderArea = renderer.renderArea; var bars = renderArea.selectAll("rect"); @@ -2043,7 +1627,6 @@ describe("Plots", function () { assert.equal(bar1.attr("x"), "450", "bar1 x is correct"); assert.equal(bar0.attr("y"), "100", "bar0 y is correct"); assert.equal(bar1.attr("y"), "200", "bar1 y is correct"); - var baseline = renderArea.select(".baseline"); assert.equal(baseline.attr("y1"), "200", "the baseline is in the correct vertical position"); assert.equal(baseline.attr("y2"), "200", "the baseline is in the correct vertical position"); @@ -2051,10 +1634,8 @@ describe("Plots", function () { assert.equal(baseline.attr("x2"), SVG_WIDTH, "the baseline ends at the edge of the chart"); verifier.end(); }); - it("baseline value can be changed; renderer updates appropriately", function () { renderer.baseline(-1); - var renderArea = renderer.renderArea; var bars = renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2063,7 +1644,6 @@ describe("Plots", function () { assert.equal(bar1.attr("height"), "50", "bar1 height is correct"); assert.equal(bar0.attr("y"), "100", "bar0 y is correct"); assert.equal(bar1.attr("y"), "300", "bar1 y is correct"); - var baseline = renderArea.select(".baseline"); assert.equal(baseline.attr("y1"), "300", "the baseline is in the correct vertical position"); assert.equal(baseline.attr("y2"), "300", "the baseline is in the correct vertical position"); @@ -2071,7 +1651,6 @@ describe("Plots", function () { assert.equal(baseline.attr("x2"), SVG_WIDTH, "the baseline ends at the edge of the chart"); verifier.end(); }); - it("bar alignment can be changed; renderer updates appropriately", function () { renderer.barAlignment("center"); var renderArea = renderer.renderArea; @@ -2082,7 +1661,6 @@ describe("Plots", function () { assert.equal(bar1.attr("width"), "10", "bar1 width is correct"); assert.equal(bar0.attr("x"), "145", "bar0 x is correct"); assert.equal(bar1.attr("x"), "445", "bar1 x is correct"); - renderer.barAlignment("right"); renderArea = renderer.renderArea; bars = renderArea.selectAll("rect"); @@ -2092,42 +1670,29 @@ describe("Plots", function () { assert.equal(bar1.attr("width"), "10", "bar1 width is correct"); assert.equal(bar0.attr("x"), "140", "bar0 x is correct"); assert.equal(bar1.attr("x"), "440", "bar1 x is correct"); - - assert.throws(function () { - return renderer.barAlignment("blargh"); - }, Error); + assert.throws(function () { return renderer.barAlignment("blargh"); }, Error); assert.equal(renderer._barAlignmentFactor, 1, "the bad barAlignment didnt break internal state"); verifier.end(); }); - it("can select and deselect bars", function () { var selectedBar = renderer.selectBar(145, 150); - assert.isNotNull(selectedBar, "clicked on a bar"); assert.equal(selectedBar.data()[0], dataset.data()[0], "the data in the bar matches the datasource"); assert.isTrue(selectedBar.classed("selected"), "the bar was classed \"selected\""); - renderer.deselectAll(); assert.isFalse(selectedBar.classed("selected"), "the bar is no longer selected"); - - selectedBar = renderer.selectBar(-1, -1); // no bars here + selectedBar = renderer.selectBar(-1, -1); assert.isNull(selectedBar, "returns null if no bar was selected"); - - selectedBar = renderer.selectBar(200, 50); // between the two bars + selectedBar = renderer.selectBar(200, 50); assert.isNull(selectedBar, "returns null if no bar was selected"); - - selectedBar = renderer.selectBar(145, 10); // above bar 0 + selectedBar = renderer.selectBar(145, 10); assert.isNull(selectedBar, "returns null if no bar was selected"); - - // the bars are now (140,100),(150,300) and (440,300),(450,350) - the - // origin is at the top left! selectedBar = renderer.selectBar({ min: 145, max: 445 }, { min: 150, max: 150 }, true); assert.isNotNull(selectedBar, "line between middle of two bars"); assert.lengthOf(selectedBar.data(), 2, "selected 2 bars (not the negative one)"); assert.equal(selectedBar.data()[0], dataset.data()[0], "the data in bar 0 matches the datasource"); assert.equal(selectedBar.data()[1], dataset.data()[2], "the data in bar 1 matches the datasource"); assert.isTrue(selectedBar.classed("selected"), "the bar was classed \"selected\""); - selectedBar = renderer.selectBar({ min: 145, max: 445 }, { min: 150, max: 350 }, true); assert.isNotNull(selectedBar, "square between middle of two bars, & over the whole area"); assert.lengthOf(selectedBar.data(), 3, "selected all the bars"); @@ -2135,33 +1700,19 @@ describe("Plots", function () { assert.equal(selectedBar.data()[1], dataset.data()[1], "the data in bar 1 matches the datasource"); assert.equal(selectedBar.data()[2], dataset.data()[2], "the data in bar 2 matches the datasource"); assert.isTrue(selectedBar.classed("selected"), "the bar was classed \"selected\""); - - // the runtime parameter validation should be strict, so no strings or - // mangled objects - assert.throws(function () { - return renderer.selectBar("blargh", 150); - }, Error); - assert.throws(function () { - return renderer.selectBar({ min: 150 }, 150); - }, Error); - + assert.throws(function () { return renderer.selectBar("blargh", 150); }, Error); + assert.throws(function () { return renderer.selectBar({ min: 150 }, 150); }, Error); verifier.end(); }); - it("shouldn't blow up if members called before the first render", function () { var brandNew = new Plottable.Plot.VerticalBar(dataset, xScale, yScale); - assert.isNotNull(brandNew.deselectAll(), "deselects return self"); assert.isNull(brandNew.selectBar(0, 0), "selects return empty"); - - brandNew._anchor(d3.select(document.createElement("svg"))); // calls `_setup()` - + brandNew._anchor(d3.select(document.createElement("svg"))); assert.isNotNull(brandNew.deselectAll(), "deselects return self after setup"); assert.isNull(brandNew.selectBar(0, 0), "selects return empty after setup"); - verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); @@ -2169,7 +1720,6 @@ describe("Plots", function () { ; }); }); - describe("Horizontal Bar Plot in Points Mode", function () { var verifier = new MultiTestVerifier(); var svg; @@ -2183,25 +1733,21 @@ describe("Plots", function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); yScale = new Plottable.Scale.Ordinal().domain(["A", "B"]).rangeType("points"); xScale = new Plottable.Scale.Linear(); - var data = [ { y: "A", x: 1 }, { y: "B", x: -1.5 }, { y: "B", x: 1 } ]; dataset = new Plottable.DataSource(data); - renderer = new Plottable.Plot.HorizontalBar(dataset, xScale, yScale); renderer.animate(false); renderer.renderTo(svg); }); - beforeEach(function () { xScale.domain([-3, 3]); renderer.baseline(0); verifier.start(); }); - it("renders correctly", function () { var renderArea = renderer.renderArea; var bars = renderArea.selectAll("rect"); @@ -2216,7 +1762,6 @@ describe("Plots", function () { assert.equal(bar1.attr("y"), "100", "bar1 y is correct"); assert.equal(bar0.attr("x"), "300", "bar0 x is correct"); assert.equal(bar1.attr("x"), "150", "bar1 x is correct"); - var baseline = renderArea.select(".baseline"); assert.equal(baseline.attr("x1"), "300", "the baseline is in the correct horizontal position"); assert.equal(baseline.attr("x2"), "300", "the baseline is in the correct horizontal position"); @@ -2224,10 +1769,8 @@ describe("Plots", function () { assert.equal(baseline.attr("y2"), SVG_HEIGHT, "the baseline ends at the bottom of the chart"); verifier.end(); }); - it("baseline value can be changed; renderer updates appropriately", function () { renderer.baseline(-1); - var renderArea = renderer.renderArea; var bars = renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2236,7 +1779,6 @@ describe("Plots", function () { assert.equal(bar1.attr("width"), "50", "bar1 width is correct"); assert.equal(bar0.attr("x"), "200", "bar0 x is correct"); assert.equal(bar1.attr("x"), "150", "bar1 x is correct"); - var baseline = renderArea.select(".baseline"); assert.equal(baseline.attr("x1"), "200", "the baseline is in the correct horizontal position"); assert.equal(baseline.attr("x2"), "200", "the baseline is in the correct horizontal position"); @@ -2244,7 +1786,6 @@ describe("Plots", function () { assert.equal(baseline.attr("y2"), SVG_HEIGHT, "the baseline ends at the bottom of the chart"); verifier.end(); }); - it("bar alignment can be changed; renderer updates appropriately", function () { renderer.barAlignment("center"); var renderArea = renderer.renderArea; @@ -2255,7 +1796,6 @@ describe("Plots", function () { assert.equal(bar1.attr("height"), "10", "bar1 height is correct"); assert.equal(bar0.attr("y"), "295", "bar0 y is correct"); assert.equal(bar1.attr("y"), "95", "bar1 y is correct"); - renderer.barAlignment("bottom"); renderArea = renderer.renderArea; bars = renderArea.selectAll("rect"); @@ -2265,14 +1805,9 @@ describe("Plots", function () { assert.equal(bar1.attr("height"), "10", "bar1 height is correct"); assert.equal(bar0.attr("y"), "290", "bar0 y is correct"); assert.equal(bar1.attr("y"), "90", "bar1 y is correct"); - - assert.throws(function () { - return renderer.barAlignment("blargh"); - }, Error); - + assert.throws(function () { return renderer.barAlignment("blargh"); }, Error); verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); @@ -2280,7 +1815,6 @@ describe("Plots", function () { ; }); }); - describe("Horizontal Bar Plot in Bands mode", function () { var verifier = new MultiTestVerifier(); var svg; @@ -2292,22 +1826,16 @@ describe("Plots", function () { var SVG_HEIGHT = 400; var axisWidth = 0; var bandWidth = 0; - - var numAttr = function (s, a) { - return parseFloat(s.attr(a)); - }; - + var numAttr = function (s, a) { return parseFloat(s.attr(a)); }; before(function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); yScale = new Plottable.Scale.Ordinal().domain(["A", "B"]); xScale = new Plottable.Scale.Linear(); - var data = [ { y: "A", x: 1 }, - { y: "B", x: 2 } + { y: "B", x: 2 }, ]; dataset = new Plottable.DataSource(data); - renderer = new Plottable.Plot.HorizontalBar(dataset, xScale, yScale); renderer.baseline(0); renderer.animate(false); @@ -2326,7 +1854,6 @@ describe("Plots", function () { } ; }); - it("renders correctly", function () { var bars = renderer.renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2337,13 +1864,10 @@ describe("Plots", function () { assert.closeTo(numAttr(bar1, "height"), 104, 2); assert.closeTo(numAttr(bar0, "width"), (600 - axisWidth) / 2, 0.01, "width is correct for bar0"); assert.closeTo(numAttr(bar1, "width"), 600 - axisWidth, 0.01, "width is correct for bar1"); - - // check that bar is aligned on the center of the scale assert.closeTo(numAttr(bar0, "y") + numAttr(bar0, "height") / 2, yScale.scale(bar0y) + bandWidth / 2, 0.01, "y pos correct for bar0"); assert.closeTo(numAttr(bar1, "y") + numAttr(bar1, "height") / 2, yScale.scale(bar1y) + bandWidth / 2, 0.01, "y pos correct for bar1"); verifier.end(); }); - it("width projector may be overwritten, and calling project queues rerender", function () { var bars = renderer.renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2363,9 +1887,7 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("GridPlot", function () { var SVG_WIDTH = 400; @@ -2374,42 +1896,35 @@ describe("Plots", function () { { x: "A", y: "U", magnitude: 0 }, { x: "B", y: "U", magnitude: 2 }, { x: "A", y: "V", magnitude: 16 }, - { x: "B", y: "V", magnitude: 8 } + { x: "B", y: "V", magnitude: 8 }, ]; - var VERIFY_CELLS = function (cells) { assert.equal(cells.length, 4); - var cellAU = d3.select(cells[0]); var cellBU = d3.select(cells[1]); var cellAV = d3.select(cells[2]); var cellBV = d3.select(cells[3]); - assert.equal(cellAU.attr("height"), "100", "cell 'AU' height is correct"); assert.equal(cellAU.attr("width"), "200", "cell 'AU' width is correct"); assert.equal(cellAU.attr("x"), "0", "cell 'AU' x coord is correct"); assert.equal(cellAU.attr("y"), "100", "cell 'AU' x coord is correct"); assert.equal(cellAU.attr("fill"), "#000000", "cell 'AU' color is correct"); - assert.equal(cellBU.attr("height"), "100", "cell 'BU' height is correct"); assert.equal(cellBU.attr("width"), "200", "cell 'BU' width is correct"); assert.equal(cellBU.attr("x"), "200", "cell 'BU' x coord is correct"); assert.equal(cellBU.attr("y"), "100", "cell 'BU' x coord is correct"); assert.equal(cellBU.attr("fill"), "#212121", "cell 'BU' color is correct"); - assert.equal(cellAV.attr("height"), "100", "cell 'AV' height is correct"); assert.equal(cellAV.attr("width"), "200", "cell 'AV' width is correct"); assert.equal(cellAV.attr("x"), "0", "cell 'AV' x coord is correct"); assert.equal(cellAV.attr("y"), "0", "cell 'AV' x coord is correct"); assert.equal(cellAV.attr("fill"), "#ffffff", "cell 'AV' color is correct"); - assert.equal(cellBV.attr("height"), "100", "cell 'BV' height is correct"); assert.equal(cellBV.attr("width"), "200", "cell 'BV' width is correct"); assert.equal(cellBV.attr("x"), "200", "cell 'BV' x coord is correct"); assert.equal(cellBV.attr("y"), "0", "cell 'BV' x coord is correct"); assert.equal(cellBV.attr("fill"), "#777777", "cell 'BV' color is correct"); }; - it("renders correctly", function () { var xScale = new Plottable.Scale.Ordinal(); var yScale = new Plottable.Scale.Ordinal(); @@ -2420,7 +1935,6 @@ describe("Plots", function () { VERIFY_CELLS(renderer.renderArea.selectAll("rect")[0]); svg.remove(); }); - it("renders correctly when data is set after construction", function () { var xScale = new Plottable.Scale.Ordinal(); var yScale = new Plottable.Scale.Ordinal(); @@ -2432,7 +1946,6 @@ describe("Plots", function () { VERIFY_CELLS(renderer.renderArea.selectAll("rect")[0]); svg.remove(); }); - it("can invert y axis correctly", function () { var xScale = new Plottable.Scale.Ordinal(); var yScale = new Plottable.Scale.Ordinal(); @@ -2440,21 +1953,17 @@ describe("Plots", function () { var svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); var renderer = new Plottable.Plot.Grid(null, xScale, yScale, colorScale).project("fill", "magnitude"); renderer.renderTo(svg); - yScale.domain(["U", "V"]); renderer.dataSource().data(DATA); - var cells = renderer.renderArea.selectAll("rect")[0]; var cellAU = d3.select(cells[0]); var cellAV = d3.select(cells[2]); cellAU.attr("fill", "#000000"); cellAU.attr("x", "0"); cellAU.attr("y", "100"); - cellAV.attr("fill", "#ffffff"); cellAV.attr("x", "0"); cellAV.attr("y", "0"); - yScale.domain(["V", "U"]); cells = renderer.renderArea.selectAll("rect")[0]; cellAU = d3.select(cells[0]); @@ -2462,19 +1971,15 @@ describe("Plots", function () { cellAU.attr("fill", "#000000"); cellAU.attr("x", "0"); cellAU.attr("y", "0"); - cellAV.attr("fill", "#ffffff"); cellAV.attr("x", "0"); cellAV.attr("y", "100"); - svg.remove(); }); }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("ScatterPlot", function () { it("the accessors properly access data, index, and metadata", function () { @@ -2485,12 +1990,8 @@ describe("Plots", function () { yScale.domain([400, 0]); var data = [{ x: 0, y: 0 }, { x: 1, y: 1 }]; var metadata = { foo: 10, bar: 20 }; - var xAccessor = function (d, i, m) { - return d.x + i * m.foo; - }; - var yAccessor = function (d, i, m) { - return m.bar; - }; + var xAccessor = function (d, i, m) { return d.x + i * m.foo; }; + var yAccessor = function (d, i, m) { return m.bar; }; var dataSource = new Plottable.DataSource(data, metadata); var renderer = new Plottable.Plot.Scatter(dataSource, xScale, yScale).project("x", xAccessor).project("y", yAccessor); renderer.renderTo(svg); @@ -2501,24 +2002,20 @@ describe("Plots", function () { assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "first circle cy is correct"); assert.closeTo(parseFloat(c2.attr("cx")), 11, 0.01, "second circle cx is correct"); assert.closeTo(parseFloat(c2.attr("cy")), 20, 0.01, "second circle cy is correct"); - data = [{ x: 2, y: 2 }, { x: 4, y: 4 }]; dataSource.data(data); assert.closeTo(parseFloat(c1.attr("cx")), 2, 0.01, "first circle cx is correct after data change"); assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "first circle cy is correct after data change"); assert.closeTo(parseFloat(c2.attr("cx")), 14, 0.01, "second circle cx is correct after data change"); assert.closeTo(parseFloat(c2.attr("cy")), 20, 0.01, "second circle cy is correct after data change"); - metadata = { foo: 0, bar: 0 }; dataSource.metadata(metadata); assert.closeTo(parseFloat(c1.attr("cx")), 2, 0.01, "first circle cx is correct after metadata change"); assert.closeTo(parseFloat(c1.attr("cy")), 0, 0.01, "first circle cy is correct after metadata change"); assert.closeTo(parseFloat(c2.attr("cx")), 4, 0.01, "second circle cx is correct after metadata change"); assert.closeTo(parseFloat(c2.attr("cy")), 0, 0.01, "second circle cy is correct after metadata change"); - svg.remove(); }); - describe("Example ScatterPlot with quadratic series", function () { var svg; var xScale; @@ -2531,23 +2028,16 @@ describe("Plots", function () { var pixelAreaPart = { xMin: 200, xMax: 600, yMin: 100, yMax: 200 }; var dataAreaFull = { xMin: 0, xMax: 9, yMin: 81, yMax: 0 }; var dataAreaPart = { xMin: 3, xMax: 9, yMin: 54, yMax: 27 }; - var colorAccessor = function (d, i, m) { - return d3.rgb(d.x, d.y, i).toString(); - }; + var colorAccessor = function (d, i, m) { return d3.rgb(d.x, d.y, i).toString(); }; var circlesInArea; var quadraticDataset = makeQuadraticSeries(10); - function getCirclePlotVerifier() { - // creates a function that verifies that circles are drawn properly after accounting for svg transform - // and then modifies circlesInArea to contain the number of circles that were discovered in the plot area circlesInArea = 0; var renderArea = circlePlot.renderArea; var renderAreaTransform = d3.transform(renderArea.attr("transform")); var translate = renderAreaTransform.translate; var scale = renderAreaTransform.scale; return function (datum, index) { - // This function takes special care to compute the position of circles after taking svg transformation - // into account. var selection = d3.select(this); var elementTransform = d3.transform(selection.attr("transform")); var elementTranslate = elementTransform.translate; @@ -2563,11 +2053,9 @@ describe("Plots", function () { }; } ; - beforeEach(function () { verifier.start(); }); - before(function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); xScale = new Plottable.Scale.Linear().domain([0, 9]); @@ -2576,7 +2064,6 @@ describe("Plots", function () { circlePlot.project("fill", colorAccessor); circlePlot.renderTo(svg); }); - it("setup is handled properly", function () { assert.deepEqual(xScale.range(), [0, SVG_WIDTH], "xScale range was set by the renderer"); assert.deepEqual(yScale.range(), [SVG_HEIGHT, 0], "yScale range was set by the renderer"); @@ -2584,7 +2071,6 @@ describe("Plots", function () { assert.equal(circlesInArea, 10, "10 circles were drawn"); verifier.end(); }); - it("rendering is idempotent", function () { circlePlot._render(); circlePlot._render(); @@ -2592,7 +2078,6 @@ describe("Plots", function () { assert.equal(circlesInArea, 10, "10 circles were drawn"); verifier.end(); }); - describe("after the scale has changed", function () { before(function () { xScale.domain([0, 3]); @@ -2600,7 +2085,6 @@ describe("Plots", function () { dataAreaFull = { xMin: 0, xMax: 3, yMin: 9, yMax: 0 }; dataAreaPart = { xMin: 1, xMax: 3, yMin: 6, yMax: 3 }; }); - it("the circles re-rendered properly", function () { var renderArea = circlePlot.renderArea; var circles = renderArea.selectAll("circle"); @@ -2609,7 +2093,6 @@ describe("Plots", function () { verifier.end(); }); }); - after(function () { if (verifier.passed) { svg.remove(); @@ -2620,9 +2103,7 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("Stacked Bar Plot", function () { var verifier = new MultiTestVerifier(); @@ -2636,16 +2117,11 @@ describe("Plots", function () { var SVG_HEIGHT = 400; var axisHeight = 0; var bandWidth = 0; - - var numAttr = function (s, a) { - return parseFloat(s.attr(a)); - }; - + var numAttr = function (s, a) { return parseFloat(s.attr(a)); }; before(function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); xScale = new Plottable.Scale.Ordinal(); yScale = new Plottable.Scale.Linear().domain([0, 3]); - var data1 = [ { x: "A", y: 1 }, { x: "B", y: 2 } @@ -2656,7 +2132,6 @@ describe("Plots", function () { ]; dataset1 = new Plottable.DataSource(data1); dataset2 = new Plottable.DataSource(data2); - renderer = new Plottable.Plot.StackedBar(xScale, yScale); renderer.addDataset(data1); renderer.addDataset(data2); @@ -2666,22 +2141,18 @@ describe("Plots", function () { axisHeight = xAxis.availableHeight; bandWidth = xScale.rangeBand(); }); - beforeEach(function () { verifier.start(); }); - afterEach(function () { verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); } ; }); - it("renders correctly", function () { var bars = renderer.renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2692,26 +2163,18 @@ describe("Plots", function () { var bar1X = bar1.data()[0].x; var bar2X = bar2.data()[0].x; var bar3X = bar3.data()[0].x; - - // check widths assert.closeTo(numAttr(bar0, "width"), bandWidth, 2); assert.closeTo(numAttr(bar1, "width"), bandWidth, 2); assert.closeTo(numAttr(bar2, "width"), bandWidth, 2); assert.closeTo(numAttr(bar3, "width"), bandWidth, 2); - - // check heights assert.closeTo(numAttr(bar0, "height"), (400 - axisHeight) / 3, 0.01, "height is correct for bar0"); assert.closeTo(numAttr(bar1, "height"), (400 - axisHeight) / 3 * 2, 0.01, "height is correct for bar1"); assert.closeTo(numAttr(bar2, "height"), (400 - axisHeight) / 3 * 2, 0.01, "height is correct for bar2"); assert.closeTo(numAttr(bar3, "height"), (400 - axisHeight) / 3, 0.01, "height is correct for bar3"); - - // check that bar is aligned on the center of the scale assert.closeTo(numAttr(bar0, "x") + numAttr(bar0, "width") / 2, xScale.scale(bar0X) + bandWidth / 2, 0.01, "x pos correct for bar0"); assert.closeTo(numAttr(bar1, "x") + numAttr(bar1, "width") / 2, xScale.scale(bar1X) + bandWidth / 2, 0.01, "x pos correct for bar1"); assert.closeTo(numAttr(bar2, "x") + numAttr(bar2, "width") / 2, xScale.scale(bar2X) + bandWidth / 2, 0.01, "x pos correct for bar2"); assert.closeTo(numAttr(bar3, "x") + numAttr(bar3, "width") / 2, xScale.scale(bar3X) + bandWidth / 2, 0.01, "x pos correct for bar3"); - - // now check y values to ensure they do indeed stack assert.closeTo(numAttr(bar0, "y"), (400 - axisHeight) / 3 * 2, 0.01, "y is correct for bar0"); assert.closeTo(numAttr(bar1, "y"), (400 - axisHeight) / 3, 0.01, "y is correct for bar1"); assert.closeTo(numAttr(bar2, "y"), 0, 0.01, "y is correct for bar2"); @@ -2720,9 +2183,7 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Plots", function () { describe("Clustered Bar Plot", function () { var verifier = new MultiTestVerifier(); @@ -2736,16 +2197,11 @@ describe("Plots", function () { var SVG_HEIGHT = 400; var axisHeight = 0; var bandWidth = 0; - - var numAttr = function (s, a) { - return parseFloat(s.attr(a)); - }; - + var numAttr = function (s, a) { return parseFloat(s.attr(a)); }; before(function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); xScale = new Plottable.Scale.Ordinal(); yScale = new Plottable.Scale.Linear().domain([0, 2]); - var data1 = [ { x: "A", y: 1 }, { x: "B", y: 2 } @@ -2756,7 +2212,6 @@ describe("Plots", function () { ]; dataset1 = new Plottable.DataSource(data1); dataset2 = new Plottable.DataSource(data2); - renderer = new Plottable.Plot.ClusteredBar(xScale, yScale); renderer.addDataset(data1); renderer.addDataset(data2); @@ -2766,22 +2221,18 @@ describe("Plots", function () { axisHeight = xAxis.availableHeight; bandWidth = xScale.rangeBand(); }); - beforeEach(function () { verifier.start(); }); - afterEach(function () { verifier.end(); }); - after(function () { if (verifier.passed) { svg.remove(); } ; }); - it("renders correctly", function () { var bars = renderer.renderArea.selectAll("rect"); var bar0 = d3.select(bars[0][0]); @@ -2792,21 +2243,15 @@ describe("Plots", function () { var bar1X = bar1.data()[0].x; var bar2X = bar2.data()[0].x; var bar3X = bar3.data()[0].x; - - // check widths var width = bandWidth / 2 * .518; assert.closeTo(numAttr(bar0, "width"), width, 2); assert.closeTo(numAttr(bar1, "width"), width, 2); assert.closeTo(numAttr(bar2, "width"), width, 2); assert.closeTo(numAttr(bar3, "width"), width, 2); - - // check heights assert.closeTo(numAttr(bar0, "height"), (400 - axisHeight) / 2, 0.01, "height is correct for bar0"); assert.closeTo(numAttr(bar1, "height"), (400 - axisHeight), 0.01, "height is correct for bar1"); assert.closeTo(numAttr(bar2, "height"), (400 - axisHeight), 0.01, "height is correct for bar2"); assert.closeTo(numAttr(bar3, "height"), (400 - axisHeight) / 2, 0.01, "height is correct for bar3"); - - // check that clustering is correct var off = renderer.innerScale.scale("_0"); assert.closeTo(numAttr(bar0, "x") + numAttr(bar0, "width") / 2, xScale.scale(bar0X) + bandWidth / 2 - off, 0.01, "x pos correct for bar0"); assert.closeTo(numAttr(bar1, "x") + numAttr(bar1, "width") / 2, xScale.scale(bar1X) + bandWidth / 2 - off, 0.01, "x pos correct for bar1"); @@ -2816,15 +2261,12 @@ describe("Plots", function () { }); }); -/// var assert = chai.assert; - describe("Broadcasters", function () { var b; var called; var cb; var listenable = { broadcaster: null }; - beforeEach(function () { b = new Plottable.Core.Broadcaster(listenable); listenable.broadcaster = b; @@ -2838,7 +2280,6 @@ describe("Broadcasters", function () { b.broadcast(); assert.isTrue(called, "callback was called"); }); - it("same listener can only be associated with one callback", function () { var called2 = false; var cb2 = function () { @@ -2851,27 +2292,23 @@ describe("Broadcasters", function () { assert.isFalse(called, "first (overwritten) callback not called"); assert.isTrue(called2, "second callback was called"); }); - it("listeners can be deregistered", function () { var listener = {}; b.registerListener(listener, cb); b.deregisterListener(listener); b.broadcast(); assert.isFalse(called, "callback was not called after deregistering only listener"); - b.registerListener(5, cb); b.registerListener(6, cb); b.deregisterAllListeners(); b.broadcast(); assert.isFalse(called, "callback was not called after deregistering all listeners"); - b.registerListener(5, cb); b.registerListener(6, cb); b.deregisterListener(5); b.broadcast(); assert.isTrue(called, "callback was called even after 1/2 listeners were deregistered"); }); - it("arguments are passed through to callback", function () { var g2 = {}; var g3 = "foo"; @@ -2885,54 +2322,40 @@ describe("Broadcasters", function () { b.broadcast(g2, g3); assert.isTrue(called, "the cb was called"); }); - it("deregistering an unregistered listener doesn't throw an error", function () { - assert.doesNotThrow(function () { - return b.deregisterListener({}); - }); + assert.doesNotThrow(function () { return b.deregisterListener({}); }); }); }); -/// var assert = chai.assert; - describe("ComponentContainer", function () { it("_addComponent()", function () { var container = new Plottable.Abstract.ComponentContainer(); var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); var c3 = new Plottable.Abstract.Component(); - assert.isTrue(container._addComponent(c1), "returns true on successful adding"); assert.deepEqual(container.components(), [c1], "component was added"); - container._addComponent(c2); assert.deepEqual(container.components(), [c1, c2], "can append components"); - container._addComponent(c3, true); assert.deepEqual(container.components(), [c3, c1, c2], "can prepend components"); - assert.isFalse(container._addComponent(null), "returns false for null arguments"); assert.deepEqual(container.components(), [c3, c1, c2], "component list was unchanged"); - assert.isFalse(container._addComponent(c1), "returns false if adding an already-added component"); assert.deepEqual(container.components(), [c3, c1, c2], "component list was unchanged"); }); - it("_removeComponent()", function () { var container = new Plottable.Abstract.ComponentContainer(); var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); container._addComponent(c1); container._addComponent(c2); - container._removeComponent(c2); assert.deepEqual(container.components(), [c1], "component 2 was removed"); - container._removeComponent(c2); assert.deepEqual(container.components(), [c1], "there are no side effects from removing already-removed components"); }); - it("empty()", function () { var container = new Plottable.Abstract.ComponentContainer(); assert.isTrue(container.empty()); @@ -2940,7 +2363,6 @@ describe("ComponentContainer", function () { container._addComponent(c1); assert.isFalse(container.empty()); }); - it("detachAll()", function () { var container = new Plottable.Abstract.ComponentContainer(); var c1 = new Plottable.Abstract.Component(); @@ -2948,32 +2370,26 @@ describe("ComponentContainer", function () { container._addComponent(c1); container._addComponent(c2); container.detachAll(); - assert.deepEqual(container.components(), [], "container was cleared of components"); }); - it("components() returns a shallow copy", function () { var container = new Plottable.Abstract.ComponentContainer(); var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); container._addComponent(c1); container._addComponent(c2); - var componentList = container.components(); componentList.pop(); assert.deepEqual(container.components(), [c1, c2], "internal list of components was not changed"); }); }); -/// var assert = chai.assert; - describe("ComponentGroups", function () { it("components in componentGroups overlap", function () { var c1 = makeFixedSizeComponent(10, 10); var c2 = new Plottable.Abstract.Component(); var c3 = new Plottable.Abstract.Component(); - var cg = new Plottable.Component.Group([c1, c2, c3]); var svg = generateSVG(400, 400); cg._anchor(svg); @@ -2989,12 +2405,10 @@ describe("ComponentGroups", function () { assertWidthHeight(t3, 400, 400, "rect3 sized correctly"); svg.remove(); }); - it("components can be added before and after anchoring", function () { var c1 = makeFixedSizeComponent(10, 10); var c2 = makeFixedSizeComponent(20, 20); var c3 = new Plottable.Abstract.Component(); - var cg = new Plottable.Component.Group([c1]); var svg = generateSVG(400, 400); cg.merge(c2)._anchor(svg); @@ -3012,35 +2426,28 @@ describe("ComponentGroups", function () { assertWidthHeight(t3, 400, 400, "rect3 sized correctly"); svg.remove(); }); - it("component fixity is computed appropriately", function () { var cg = new Plottable.Component.Group(); var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); - cg.merge(c1).merge(c2); assert.isFalse(cg._isFixedHeight(), "height not fixed when both components unfixed"); assert.isFalse(cg._isFixedWidth(), "width not fixed when both components unfixed"); - fixComponentSize(c1, 10, 10); assert.isFalse(cg._isFixedHeight(), "height not fixed when one component unfixed"); assert.isFalse(cg._isFixedWidth(), "width not fixed when one component unfixed"); - fixComponentSize(c2, null, 10); assert.isTrue(cg._isFixedHeight(), "height fixed when both components fixed"); assert.isFalse(cg._isFixedWidth(), "width unfixed when one component unfixed"); }); - it("componentGroup subcomponents have xOffset, yOffset of 0", function () { var cg = new Plottable.Component.Group(); var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); cg.merge(c1).merge(c2); - var svg = generateSVG(); cg._anchor(svg); cg._computeLayout(50, 50, 350, 350); - var cgTranslate = d3.transform(cg.element.attr("transform")).translate; var c1Translate = d3.transform(c1.element.attr("transform")).translate; var c2Translate = d3.transform(c2.element.attr("transform")).translate; @@ -3052,46 +2459,33 @@ describe("ComponentGroups", function () { assert.equal(c2Translate[1], 0, "componentGroup has 0 yOffset"); svg.remove(); }); - it("detach() and _removeComponent work correctly for componentGroup", function () { var c1 = new Plottable.Abstract.Component().classed("component-1", true); var c2 = new Plottable.Abstract.Component().classed("component-2", true); var cg = new Plottable.Component.Group([c1, c2]); - var svg = generateSVG(200, 200); cg.renderTo(svg); - var c1Node = svg.select(".component-1").node(); var c2Node = svg.select(".component-2").node(); - assert.isNotNull(c1Node, "component 1 was added to the DOM"); assert.isNotNull(c2Node, "component 2 was added to the DOM"); - c2.detach(); - c1Node = svg.select(".component-1").node(); c2Node = svg.select(".comopnent-2").node(); - assert.isNotNull(c1Node, "component 1 is still in the DOM"); assert.isNull(c2Node, "component 2 was removed from the DOM"); - cg.detach(); var cgNode = svg.select(".component-group").node(); c1Node = svg.select(".component-1").node(); - assert.isNull(cgNode, "component group was removed from the DOM"); assert.isNull(c1Node, "componet 1 was also removed from the DOM"); - cg.renderTo(svg); cgNode = svg.select(".component-group").node(); c1Node = svg.select(".component-1").node(); - assert.isNotNull(cgNode, "component group was added back to the DOM"); assert.isNotNull(c1Node, "componet 1 was also added back to the DOM"); - svg.remove(); }); - it("detachAll() works as expected", function () { var cg = new Plottable.Component.Group(); var c1 = new Plottable.Abstract.Component(); @@ -3107,14 +2501,12 @@ describe("ComponentGroups", function () { assert.isFalse(c3._isAnchored, "c3 was detached"); assert.lengthOf(cg.components(), 0, "cg has no components"); }); - describe("ComponentGroup._requestedSpace works as expected", function () { it("_works for an empty ComponentGroup", function () { var cg = new Plottable.Component.Group(); var request = cg._requestedSpace(10, 10); verifySpaceRequest(request, 0, 0, false, false, ""); }); - it("works for a ComponentGroup with only proportional-size components", function () { var cg = new Plottable.Component.Group(); var c1 = new Plottable.Abstract.Component(); @@ -3123,7 +2515,6 @@ describe("ComponentGroups", function () { var request = cg._requestedSpace(10, 10); verifySpaceRequest(request, 0, 0, false, false, ""); }); - it("works when there are fixed-size components", function () { var cg = new Plottable.Component.Group(); var c1 = new Plottable.Abstract.Component(); @@ -3136,13 +2527,11 @@ describe("ComponentGroups", function () { verifySpaceRequest(request, 0, 50, false, true, ""); }); }); - describe("Component.merge works as expected", function () { var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); var c3 = new Plottable.Abstract.Component(); var c4 = new Plottable.Abstract.Component(); - it("Component.merge works as expected (Component.merge Component)", function () { var cg = c1.merge(c2); var innerComponents = cg._components; @@ -3150,7 +2539,6 @@ describe("ComponentGroups", function () { assert.equal(innerComponents[0], c1, "first component correct"); assert.equal(innerComponents[1], c2, "second component correct"); }); - it("Component.merge works as expected (Component.merge ComponentGroup)", function () { var cg = new Plottable.Component.Group([c2, c3, c4]); var cg2 = c1.merge(cg); @@ -3160,7 +2548,6 @@ describe("ComponentGroups", function () { assert.equal(components[0], c1, "first component in front"); assert.equal(components[1], c2, "second component is second"); }); - it("Component.merge works as expected (ComponentGroup.merge Component)", function () { var cg = new Plottable.Component.Group([c1, c2, c3]); var cg2 = cg.merge(c4); @@ -3170,7 +2557,6 @@ describe("ComponentGroups", function () { assert.equal(components[0], c1, "first is first"); assert.equal(components[3], c4, "fourth is fourth"); }); - it("Component.merge works as expected (ComponentGroup.merge ComponentGroup)", function () { var cg1 = new Plottable.Component.Group([c1, c2]); var cg2 = new Plottable.Component.Group([c3, c4]); @@ -3186,18 +2572,14 @@ describe("ComponentGroups", function () { }); }); -/// var assert = chai.assert; - function assertComponentXY(component, x, y, message) { - // use to examine the private variables var translate = d3.transform(component.element.attr("transform")).translate; var xActual = translate[0]; var yActual = translate[1]; assert.equal(xActual, x, "X: " + message); assert.equal(yActual, y, "Y: " + message); } - describe("Component behavior", function () { var svg; var c; @@ -3207,7 +2589,6 @@ describe("Component behavior", function () { svg = generateSVG(SVG_WIDTH, SVG_HEIGHT); c = new Plottable.Abstract.Component(); }); - describe("anchor", function () { it("anchoring works as expected", function () { c._anchor(svg); @@ -3215,20 +2596,16 @@ describe("Component behavior", function () { assert.isTrue(svg.classed("plottable"), " was given \"plottable\" CSS class"); svg.remove(); }); - it("can re-anchor to a different element", function () { c._anchor(svg); - var svg2 = generateSVG(SVG_WIDTH, SVG_HEIGHT); c._anchor(svg2); assert.equal(c.element.node(), svg2.select("g").node(), "the component re-achored under the second "); assert.isTrue(svg2.classed("plottable"), "second was given \"plottable\" CSS class"); - svg.remove(); svg2.remove(); }); }); - describe("computeLayout", function () { it("computeLayout defaults and updates intelligently", function () { c._anchor(svg); @@ -3237,24 +2614,18 @@ describe("Component behavior", function () { assert.equal(c.availableHeight, SVG_HEIGHT, "computeLayout defaulted height to svg height"); assert.equal(c.xOrigin, 0, "xOrigin defaulted to 0"); assert.equal(c.yOrigin, 0, "yOrigin defaulted to 0"); - svg.attr("width", 2 * SVG_WIDTH).attr("height", 2 * SVG_HEIGHT); c._computeLayout(); assert.equal(c.availableWidth, 2 * SVG_WIDTH, "computeLayout updated width to new svg width"); assert.equal(c.availableHeight, 2 * SVG_HEIGHT, "computeLayout updated height to new svg height"); assert.equal(c.xOrigin, 0, "xOrigin is still 0"); assert.equal(c.yOrigin, 0, "yOrigin is still 0"); - svg.remove(); }); - it("computeLayout works with CSS layouts", function () { - // Manually size parent var parent = d3.select(svg.node().parentNode); parent.style("width", "400px"); parent.style("height", "200px"); - - // Remove width/height attributes and style with CSS svg.attr("width", null).attr("height", null); c._anchor(svg); c._computeLayout(); @@ -3262,46 +2633,32 @@ describe("Component behavior", function () { assert.equal(c.availableHeight, 200, "defaults to height of parent if width is not specified on "); assert.equal(c.xOrigin, 0, "xOrigin defaulted to 0"); assert.equal(c.yOrigin, 0, "yOrigin defaulted to 0"); - svg.style("width", "50%").style("height", "50%"); c._computeLayout(); - assert.equal(c.availableWidth, 200, "computeLayout defaulted width to svg width"); assert.equal(c.availableHeight, 100, "computeLayout defaulted height to svg height"); assert.equal(c.xOrigin, 0, "xOrigin defaulted to 0"); assert.equal(c.yOrigin, 0, "yOrigin defaulted to 0"); - svg.style("width", "25%").style("height", "25%"); - c._computeLayout(); - assert.equal(c.availableWidth, 100, "computeLayout updated width to new svg width"); assert.equal(c.availableHeight, 50, "computeLayout updated height to new svg height"); assert.equal(c.xOrigin, 0, "xOrigin is still 0"); assert.equal(c.yOrigin, 0, "yOrigin is still 0"); - - // reset test page DOM parent.style("width", "auto"); parent.style("height", "auto"); svg.remove(); }); - it("computeLayout will not default when attached to non-root node", function () { var g = svg.append("g"); c._anchor(g); - assert.throws(function () { - return c._computeLayout(); - }, "null arguments"); + assert.throws(function () { return c._computeLayout(); }, "null arguments"); svg.remove(); }); - it("computeLayout throws an error when called on un-anchored component", function () { - assert.throws(function () { - return c._computeLayout(); - }, Error, "anchor must be called before computeLayout"); + assert.throws(function () { return c._computeLayout(); }, Error, "anchor must be called before computeLayout"); svg.remove(); }); - it("computeLayout uses its arguments apropriately", function () { var g = svg.append("g"); var xOff = 10; @@ -3317,7 +2674,6 @@ describe("Component behavior", function () { svg.remove(); }); }); - it("subelement containers are ordered properly", function () { c.renderTo(svg); var gs = c.element.selectAll("g"); @@ -3331,49 +2687,39 @@ describe("Component behavior", function () { assert.isTrue(g3.classed("box-container"), "the fourth g is a box container"); svg.remove(); }); - it("fixed-width component will align to the right spot", function () { fixComponentSize(c, 100, 100); c._anchor(svg); c._computeLayout(); assertComponentXY(c, 0, 0, "top-left component aligns correctly"); - c.xAlign("CENTER").yAlign("CENTER"); c._computeLayout(); assertComponentXY(c, 150, 100, "center component aligns correctly"); - c.xAlign("RIGHT").yAlign("BOTTOM"); c._computeLayout(); assertComponentXY(c, 300, 200, "bottom-right component aligns correctly"); svg.remove(); }); - it("components can be offset relative to their alignment, and throw errors if there is insufficient space", function () { fixComponentSize(c, 100, 100); c._anchor(svg); c.xOffset(20).yOffset(20); c._computeLayout(); assertComponentXY(c, 20, 20, "top-left component offsets correctly"); - c.xAlign("CENTER").yAlign("CENTER"); c._computeLayout(); assertComponentXY(c, 170, 120, "center component offsets correctly"); - c.xAlign("RIGHT").yAlign("BOTTOM"); c._computeLayout(); assertComponentXY(c, 320, 220, "bottom-right component offsets correctly"); - c.xOffset(0).yOffset(0); c._computeLayout(); assertComponentXY(c, 300, 200, "bottom-right component offset resets"); - c.xOffset(-20).yOffset(-30); c._computeLayout(); assertComponentXY(c, 280, 170, "negative offsets work properly"); - svg.remove(); }); - it("component defaults are as expected", function () { var layout = c._requestedSpace(1, 1); assert.equal(layout.width, 0, "requested width defaults to 0"); @@ -3386,7 +2732,6 @@ describe("Component behavior", function () { assert.equal(c._yOffset, 0, "yOffset defaults to 0"); svg.remove(); }); - it("clipPath works as expected", function () { assert.isFalse(c.clipPathEnabled, "clipPathEnabled defaults to false"); c.clipPathEnabled = true; @@ -3395,18 +2740,13 @@ describe("Component behavior", function () { c._computeLayout(0, 0, 100, 100); c._render(); var expectedClipPathURL = "url(#clipPath" + expectedClipPathID + ")"; - - // IE 9 has clipPath like 'url("#clipPath")', must accomodate - var normalizeClipPath = function (s) { - return s.replace(/"/g, ""); - }; + var normalizeClipPath = function (s) { return s.replace(/"/g, ""); }; assert.isTrue(normalizeClipPath(c.element.attr("clip-path")) === expectedClipPathURL, "the element has clip-path url attached"); var clipRect = c.boxContainer.select(".clip-rect"); assert.equal(clipRect.attr("width"), 100, "the clipRect has an appropriate width"); assert.equal(clipRect.attr("height"), 100, "the clipRect has an appropriate height"); svg.remove(); }); - it("componentID works as expected", function () { var expectedID = Plottable.Abstract.PlottableObject.nextID; var c1 = new Plottable.Abstract.Component(); @@ -3415,17 +2755,13 @@ describe("Component behavior", function () { assert.equal(c2._plottableID, expectedID + 1, "future components increment appropriately"); svg.remove(); }); - it("boxes work as expected", function () { - assert.throws(function () { - return c.addBox("pre-anchor"); - }, Error, "Adding boxes before anchoring is currently disallowed"); + assert.throws(function () { return c.addBox("pre-anchor"); }, Error, "Adding boxes before anchoring is currently disallowed"); c.renderTo(svg); c.addBox("post-anchor"); var e = c.element; var boxContainer = e.select(".box-container"); var boxStrings = [".bounding-box", ".post-anchor"]; - boxStrings.forEach(function (s) { var box = boxContainer.select(s); assert.isNotNull(box.node(), s + " box was created and placed inside boxContainer"); @@ -3435,7 +2771,6 @@ describe("Component behavior", function () { }); svg.remove(); }); - it("hitboxes are created iff there are registered interactions", function () { function verifyHitbox(component) { var hitBox = component.hitBox; @@ -3445,35 +2780,27 @@ describe("Component behavior", function () { assert.isTrue(hitBoxFilled, hitBoxFill + " <- this should be filled, so the hitbox will detect events"); assert.equal(hitBox.style("opacity"), "0", "the hitBox is transparent, otherwise it would look weird"); } - c._anchor(svg); assert.isUndefined(c.hitBox, "no hitBox was created when there were no registered interactions"); svg.remove(); svg = generateSVG(); - c = new Plottable.Abstract.Component(); var i = new Plottable.Abstract.Interaction(c).registerWithComponent(); c._anchor(svg); verifyHitbox(c); svg.remove(); svg = generateSVG(); - c = new Plottable.Abstract.Component(); c._anchor(svg); i = new Plottable.Abstract.Interaction(c).registerWithComponent(); verifyHitbox(c); svg.remove(); }); - it("interaction registration works properly", function () { var hitBox1 = null; var hitBox2 = null; - var interaction1 = { _anchor: function (hb) { - return hitBox1 = hb.node(); - } }; - var interaction2 = { _anchor: function (hb) { - return hitBox2 = hb.node(); - } }; + var interaction1 = { _anchor: function (hb) { return hitBox1 = hb.node(); } }; + var interaction2 = { _anchor: function (hb) { return hitBox2 = hb.node(); } }; c.registerInteraction(interaction1); c.renderTo(svg); c.registerInteraction(interaction2); @@ -3482,17 +2809,11 @@ describe("Component behavior", function () { assert.equal(hitBox2, hitNode, "hitBox2 was registerd"); svg.remove(); }); - it("errors are thrown on bad alignments", function () { - assert.throws(function () { - return c.xAlign("foo"); - }, Error, "Unsupported alignment"); - assert.throws(function () { - return c.yAlign("foo"); - }, Error, "Unsupported alignment"); + assert.throws(function () { return c.xAlign("foo"); }, Error, "Unsupported alignment"); + assert.throws(function () { return c.yAlign("foo"); }, Error, "Unsupported alignment"); svg.remove(); }); - it("css classing works as expected", function () { assert.isFalse(c.classed("CSS-PREANCHOR-KEEP")); c.classed("CSS-PREANCHOR-KEEP", true); @@ -3501,7 +2822,6 @@ describe("Component behavior", function () { assert.isTrue(c.classed("CSS-PREANCHOR-REMOVE")); c.classed("CSS-PREANCHOR-REMOVE", false); assert.isFalse(c.classed("CSS-PREANCHOR-REMOVE")); - c._anchor(svg); assert.isTrue(c.classed("CSS-PREANCHOR-KEEP")); assert.isFalse(c.classed("CSS-PREANCHOR-REMOVE")); @@ -3514,42 +2834,29 @@ describe("Component behavior", function () { assert.equal(c.classed(undefined, true), c, "returns this when classed called w/ undefined and true"); svg.remove(); }); - it("detach() works as expected", function () { var cbCalled = 0; - var cb = function (b) { - return cbCalled++; - }; + var cb = function (b) { return cbCalled++; }; var b = new Plottable.Core.Broadcaster(null); - var c1 = new Plottable.Abstract.Component(); - b.registerListener(c1, cb); - c1.renderTo(svg); b.broadcast(); assert.equal(cbCalled, 1, "the callback was called"); assert.isTrue(svg.node().hasChildNodes(), "the svg has children"); c1.detach(); - b.broadcast(); assert.equal(cbCalled, 2, "the callback is still attached to the component"); assert.isFalse(svg.node().hasChildNodes(), "the svg has no children"); - svg.remove(); }); - it("can't reuse component if it's been remove()-ed", function () { var c1 = new Plottable.Abstract.Component(); c1.renderTo(svg); c1.remove(); - - assert.throws(function () { - return c1.renderTo(svg); - }, "reuse"); + assert.throws(function () { return c1.renderTo(svg); }, "reuse"); svg.remove(); }); - it("_invalidateLayout works as expected", function () { var cg = new Plottable.Component.Group(); var c = makeFixedSizeComponent(10, 10); @@ -3563,23 +2870,18 @@ describe("Component behavior", function () { assert.equal(cg.availableWidth, 50, "invalidateLayout propagated to parent and caused resized width"); svg.remove(); }); - it("components can be detached even if not anchored", function () { var c = new Plottable.Abstract.Component(); - c.detach(); // no error thrown + c.detach(); svg.remove(); }); }); -/// var assert = chai.assert; - describe("DataSource", function () { it("Updates listeners when the data is changed", function () { var ds = new Plottable.DataSource(); - var newData = [1, 2, 3]; - var callbackCalled = false; var callback = function (listenable) { assert.equal(listenable, ds, "Callback received the DataSource as the first argument"); @@ -3587,16 +2889,12 @@ describe("DataSource", function () { callbackCalled = true; }; ds.broadcaster.registerListener(null, callback); - ds.data(newData); assert.isTrue(callbackCalled, "callback was called when the data was changed"); }); - it("Updates listeners when the metadata is changed", function () { var ds = new Plottable.DataSource(); - var newMetadata = "blargh"; - var callbackCalled = false; var callback = function (listenable) { assert.equal(listenable, ds, "Callback received the DataSource as the first argument"); @@ -3604,42 +2902,28 @@ describe("DataSource", function () { callbackCalled = true; }; ds.broadcaster.registerListener(null, callback); - ds.metadata(newMetadata); assert.isTrue(callbackCalled, "callback was called when the metadata was changed"); }); - it("_getExtent works as expected", function () { var data = [1, 2, 3, 4, 1]; var metadata = { foo: 11 }; var dataSource = new Plottable.DataSource(data, metadata); var plot = new Plottable.Abstract.Plot(dataSource); - var apply = function (a) { - return Plottable.Util.Methods._applyAccessor(a, plot); - }; - var a1 = function (d, i, m) { - return d + i - 2; - }; + var apply = function (a) { return Plottable.Util.Methods._applyAccessor(a, plot); }; + var a1 = function (d, i, m) { return d + i - 2; }; assert.deepEqual(dataSource._getExtent(apply(a1)), [-1, 5], "extent for numerical data works properly"); - var a2 = function (d, i, m) { - return d + m.foo; - }; + var a2 = function (d, i, m) { return d + m.foo; }; assert.deepEqual(dataSource._getExtent(apply(a2)), [12, 15], "extent uses metadata appropriately"); dataSource.metadata({ foo: -1 }); assert.deepEqual(dataSource._getExtent(apply(a2)), [0, 3], "metadata change is reflected in extent results"); - var a3 = function (d, i, m) { - return "_" + d; - }; + var a3 = function (d, i, m) { return "_" + d; }; assert.deepEqual(dataSource._getExtent(apply(a3)), ["_1", "_2", "_3", "_4"], "extent works properly on string domains (no repeats)"); }); }); -/// var assert = chai.assert; - function generateBasicTable(nRows, nCols) { - // makes a table with exactly nRows * nCols children in a regular grid, with each - // child being a basic component var table = new Plottable.Component.Table(); var rows = []; var components = []; @@ -3652,13 +2936,11 @@ function generateBasicTable(nRows, nCols) { } return { "table": table, "components": components }; } - describe("Tables", function () { it("tables are classed properly", function () { var table = new Plottable.Component.Table(); assert.isTrue(table.classed("table")); }); - it("padTableToSize works properly", function () { var t = new Plottable.Component.Table(); assert.deepEqual(t.rows, [], "the table rows is an empty list"); @@ -3669,15 +2951,11 @@ describe("Tables", function () { assert.lengthOf(rows, 1, "there is one row"); assert.lengthOf(row, 1, "the row has one element"); assert.isNull(firstComponent, "the row only has a null component"); - t.padTableToSize(5, 2); assert.lengthOf(rows, 5, "there are five rows"); - rows.forEach(function (r) { - return assert.lengthOf(r, 2, "there are two columsn per row"); - }); + rows.forEach(function (r) { return assert.lengthOf(r, 2, "there are two columsn per row"); }); assert.equal(rows[0][0], firstComponent, "the first component is unchanged"); }); - it("table constructor can take a list of lists of components", function () { var c0 = new Plottable.Abstract.Component(); var row1 = [null, c0]; @@ -3688,7 +2966,6 @@ describe("Tables", function () { table.addComponent(2, 2, c1); assert.equal(table.rows[2][2], c1, "the inserted component went to the right spot"); }); - it("tables can be constructed by adding components in matrix style", function () { var table = new Plottable.Component.Table(); var c1 = new Plottable.Abstract.Component(); @@ -3704,7 +2981,6 @@ describe("Tables", function () { assert.isNull(rows[0][1], "component at (0, 1) is null"); assert.isNull(rows[1][0], "component at (1, 0) is null"); }); - it("can't add a component where one already exists", function () { var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); @@ -3712,67 +2988,45 @@ describe("Tables", function () { var t = new Plottable.Component.Table(); t.addComponent(0, 2, c1); t.addComponent(0, 0, c2); - assert.throws(function () { - return t.addComponent(0, 2, c3); - }, Error, "component already exists"); + assert.throws(function () { return t.addComponent(0, 2, c3); }, Error, "component already exists"); }); - it("addComponent works even if a component is added with a high column and low row index", function () { - // Solves #180, a weird bug var t = new Plottable.Component.Table(); var svg = generateSVG(); t.addComponent(1, 0, new Plottable.Abstract.Component()); t.addComponent(0, 2, new Plottable.Abstract.Component()); - t.renderTo(svg); //would throw an error without the fix (tested); + t.renderTo(svg); svg.remove(); }); - it("basic table with 2 rows 2 cols lays out properly", function () { var tableAndcomponents = generateBasicTable(2, 2); var table = tableAndcomponents.table; var components = tableAndcomponents.components; - var svg = generateSVG(); table.renderTo(svg); - - var elements = components.map(function (r) { - return r.element; - }); - var translates = elements.map(function (e) { - return getTranslate(e); - }); + var elements = components.map(function (r) { return r.element; }); + var translates = elements.map(function (e) { return getTranslate(e); }); assert.deepEqual(translates[0], [0, 0], "first element is centered at origin"); assert.deepEqual(translates[1], [200, 0], "second element is located properly"); assert.deepEqual(translates[2], [0, 200], "third element is located properly"); assert.deepEqual(translates[3], [200, 200], "fourth element is located properly"); - var bboxes = elements.map(function (e) { - return Plottable.Util.DOM.getBBox(e); - }); + var bboxes = elements.map(function (e) { return Plottable.Util.DOM.getBBox(e); }); bboxes.forEach(function (b) { assert.equal(b.width, 200, "bbox is 200 pixels wide"); assert.equal(b.height, 200, "bbox is 200 pixels tall"); }); svg.remove(); }); - it("table with 2 rows 2 cols and margin/padding lays out properly", function () { var tableAndcomponents = generateBasicTable(2, 2); var table = tableAndcomponents.table; var components = tableAndcomponents.components; table.padding(5, 5); - var svg = generateSVG(415, 415); table.renderTo(svg); - - var elements = components.map(function (r) { - return r.element; - }); - var translates = elements.map(function (e) { - return getTranslate(e); - }); - var bboxes = elements.map(function (e) { - return Plottable.Util.DOM.getBBox(e); - }); + var elements = components.map(function (r) { return r.element; }); + var translates = elements.map(function (e) { return getTranslate(e); }); + var bboxes = elements.map(function (e) { return Plottable.Util.DOM.getBBox(e); }); assert.deepEqual(translates[0], [0, 0], "first element is centered properly"); assert.deepEqual(translates[1], [210, 0], "second element is located properly"); assert.deepEqual(translates[2], [0, 210], "third element is located properly"); @@ -3783,46 +3037,24 @@ describe("Tables", function () { }); svg.remove(); }); - it("table with fixed-size objects on every side lays out properly", function () { var svg = generateSVG(); var c4 = new Plottable.Abstract.Component(); - - // [0 1 2] \\ - // [3 4 5] \\ - // [6 7 8] \\ - // give the axis-like objects a minimum var c1 = makeFixedSizeComponent(null, 30); var c7 = makeFixedSizeComponent(null, 30); var c3 = makeFixedSizeComponent(50, null); var c5 = makeFixedSizeComponent(50, null); - var table = new Plottable.Component.Table([ - [null, c1, null], - [c3, c4, c5], - [null, c7, null]]); - + var table = new Plottable.Component.Table([[null, c1, null], [c3, c4, c5], [null, c7, null]]); var components = [c1, c3, c4, c5, c7]; - table.renderTo(svg); - - var elements = components.map(function (r) { - return r.element; - }); - var translates = elements.map(function (e) { - return getTranslate(e); - }); - var bboxes = elements.map(function (e) { - return Plottable.Util.DOM.getBBox(e); - }); - - // test the translates + var elements = components.map(function (r) { return r.element; }); + var translates = elements.map(function (e) { return getTranslate(e); }); + var bboxes = elements.map(function (e) { return Plottable.Util.DOM.getBBox(e); }); assert.deepEqual(translates[0], [50, 0], "top axis translate"); assert.deepEqual(translates[4], [50, 370], "bottom axis translate"); assert.deepEqual(translates[1], [0, 30], "left axis translate"); assert.deepEqual(translates[3], [350, 30], "right axis translate"); assert.deepEqual(translates[2], [50, 30], "plot translate"); - - // test the bboxes assertBBoxEquivalence(bboxes[0], [300, 30], "top axis bbox"); assertBBoxEquivalence(bboxes[4], [300, 30], "bottom axis bbox"); assertBBoxEquivalence(bboxes[1], [50, 340], "left axis bbox"); @@ -3830,14 +3062,11 @@ describe("Tables", function () { assertBBoxEquivalence(bboxes[2], [300, 340], "plot bbox"); svg.remove(); }); - it("table space fixity calculates properly", function () { var tableAndcomponents = generateBasicTable(3, 3); var table = tableAndcomponents.table; var components = tableAndcomponents.components; - components.forEach(function (c) { - return fixComponentSize(c, 10, 10); - }); + components.forEach(function (c) { return fixComponentSize(c, 10, 10); }); assert.isTrue(table._isFixedWidth(), "fixed width when all subcomponents fixed width"); assert.isTrue(table._isFixedHeight(), "fixedHeight when all subcomponents fixed height"); fixComponentSize(components[0], null, 10); @@ -3848,32 +3077,22 @@ describe("Tables", function () { assert.isTrue(table._isFixedWidth(), "width fixed again once no subcomponent width not fixed"); assert.isFalse(table._isFixedHeight(), "height unfixed now that a subcomponent has unfixed height"); }); - it.skip("table._requestedSpace works properly", function () { - // [0 1] - // [2 3] var c0 = new Plottable.Abstract.Component(); var c1 = makeFixedSizeComponent(50, 50); var c2 = makeFixedSizeComponent(20, 50); var c3 = makeFixedSizeComponent(20, 20); - var table = new Plottable.Component.Table([[c0, c1], [c2, c3]]); - var spaceRequest = table._requestedSpace(30, 30); verifySpaceRequest(spaceRequest, 30, 30, true, true, "1"); - spaceRequest = table._requestedSpace(50, 50); verifySpaceRequest(spaceRequest, 50, 50, true, true, "2"); - spaceRequest = table._requestedSpace(90, 90); verifySpaceRequest(spaceRequest, 70, 90, false, true, "3"); - spaceRequest = table._requestedSpace(200, 200); verifySpaceRequest(spaceRequest, 70, 100, false, false, "4"); }); - describe("table.iterateLayout works properly", function () { - // This test battery would have caught #405 function verifyLayoutResult(result, cPS, rPS, gW, gH, wW, wH, id) { assert.deepEqual(result.colProportionalSpace, cPS, "colProportionalSpace:" + id); assert.deepEqual(result.rowProportionalSpace, rPS, "rowProportionalSpace:" + id); @@ -3882,28 +3101,25 @@ describe("Tables", function () { assert.deepEqual(result.wantsWidth, wW, "wantsWidth:" + id); assert.deepEqual(result.wantsHeight, wH, "wantsHeight:" + id); } - var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); var c3 = new Plottable.Abstract.Component(); var c4 = new Plottable.Abstract.Component(); var table = new Plottable.Component.Table([ [c1, c2], - [c3, c4]]); - + [c3, c4] + ]); it("iterateLayout works in the easy case where there is plenty of space and everything is satisfied on first go", function () { fixComponentSize(c1, 50, 50); fixComponentSize(c4, 20, 10); var result = table.iterateLayout(500, 500); verifyLayoutResult(result, [215, 215], [220, 220], [50, 20], [50, 10], false, false, ""); }); - it.skip("iterateLayout works in the difficult case where there is a shortage of space and layout requires iterations", function () { fixComponentSize(c1, 490, 50); var result = table.iterateLayout(500, 500); verifyLayoutResult(result, [0, 0], [220, 220], [480, 20], [50, 10], true, false, ""); }); - it("iterateLayout works in the case where all components are fixed-size", function () { fixComponentSize(c1, 50, 50); fixComponentSize(c2, 50, 50); @@ -3911,16 +3127,11 @@ describe("Tables", function () { fixComponentSize(c4, 50, 50); var result = table.iterateLayout(100, 100); verifyLayoutResult(result, [0, 0], [0, 0], [50, 50], [50, 50], false, false, "..when there's exactly enough space"); - result = table.iterateLayout(80, 80); verifyLayoutResult(result, [0, 0], [0, 0], [40, 40], [40, 40], true, true, "..when there's not enough space"); - result = table.iterateLayout(120, 120); - - // If there is extra space in a fixed-size table, the extra space should not be allocated to proportional space verifyLayoutResult(result, [0, 0], [0, 0], [50, 50], [50, 50], false, false, "..when there's extra space"); }); - it.skip("iterateLayout works in the tricky case when components can be unsatisfied but request little space", function () { table = new Plottable.Component.Table([[c1, c2]]); fixComponentSize(c1, null, null); @@ -3938,7 +3149,6 @@ describe("Tables", function () { verifyLayoutResult(result, [150, 0], [0], [0, 0], [200], true, false, "when there's insufficient space"); }); }); - describe("table._removeComponent works properly", function () { var c1 = new Plottable.Abstract.Component(); var c2 = new Plottable.Abstract.Component(); @@ -3952,36 +3162,27 @@ describe("Tables", function () { table._removeComponent(c4); assert.deepEqual(table.rows, [[c1, c2], [c3, null], [c5, c6]], "remove one element"); }); - it("table._removeComponent does nothing when component is not found", function () { table = new Plottable.Component.Table([[c1, c2], [c3, c4]]); table._removeComponent(c5); - assert.deepEqual(table.rows, [[c1, c2], [c3, c4]], "remove nonexistent component"); }); - it("table._removeComponent removing component twice should have same effect as removing it once", function () { table = new Plottable.Component.Table([[c1, c2, c3], [c4, c5, c6]]); - table._removeComponent(c1); assert.deepEqual(table.rows, [[null, c2, c3], [c4, c5, c6]], "item twice"); - table._removeComponent(c1); assert.deepEqual(table.rows, [[null, c2, c3], [c4, c5, c6]], "item twice"); }); - it("table._removeComponent doesn't do anything weird when called with null", function () { table = new Plottable.Component.Table([[c1, null], [c2, c3]]); - table._removeComponent(null); assert.deepEqual(table.rows, [[c1, null], [c2, c3]]); }); }); }); -/// var assert = chai.assert; - describe("Domainer", function () { var scale; var domainer; @@ -3989,13 +3190,11 @@ describe("Domainer", function () { scale = new Plottable.Scale.Linear(); domainer = new Plottable.Domainer(); }); - it("pad() works in general case", function () { scale.updateExtent("1", "x", [100, 200]); scale.domainer(new Plottable.Domainer().pad(0.2)); assert.deepEqual(scale.domain(), [90, 210]); }); - it("pad() works for date scales", function () { var timeScale = new Plottable.Scale.Time(); var f = d3.time.format("%x"); @@ -4012,7 +3211,6 @@ describe("Domainer", function () { assert.equal(dd1.valueOf(), dd1.valueOf(), "date1 is not NaN"); assert.equal(dd2.valueOf(), dd2.valueOf(), "date2 is not NaN"); }); - it("pad() works on log scales", function () { var logScale = new Plottable.Scale.Log(); logScale.updateExtent("1", "x", [10, 100]); @@ -4029,39 +3227,30 @@ describe("Domainer", function () { assert.closeTo(logScale.domain()[0], 1, 0.001); assert.closeTo(logScale.domain()[1], 1000, 0.001); }); - it("pad() defaults to [v-1, v+1] if there's only one numeric value", function () { domainer.pad(); var domain = domainer.computeDomain([[5, 5]], scale); assert.deepEqual(domain, [4, 6]); }); - it("pad() defaults to [v-1 day, v+1 day] if there's only one date value", function () { var d = new Date(2000, 5, 5); var dayBefore = new Date(2000, 5, 4); var dayAfter = new Date(2000, 5, 6); var timeScale = new Plottable.Scale.Time(); - - // the result of computeDomain() will be number[], but when it - // gets fed back into timeScale, it will be adjusted back to a Date. - // That's why I'm using updateExtent() instead of domainer.computeDomain() timeScale.updateExtent("1", "x", [d, d]); timeScale.domainer(new Plottable.Domainer().pad()); assert.deepEqual(timeScale.domain(), [dayBefore, dayAfter]); }); - it("pad() only takes the last value", function () { domainer.pad(1000).pad(4).pad(0.1); var domain = domainer.computeDomain([[100, 200]], scale); assert.deepEqual(domain, [95, 205]); }); - it("pad() will pad beyond 0 by default", function () { domainer.pad(0.1); var domain = domainer.computeDomain([[0, 100]], scale); assert.deepEqual(domain, [-5, 105]); }); - it("pad() works with scales that have 0-size domain", function () { scale.domain([5, 5]); var domain = domainer.computeDomain([[0, 100]], scale); @@ -4070,7 +3259,6 @@ describe("Domainer", function () { domain = domainer.computeDomain([[0, 100]], scale); assert.deepEqual(domain, [0, 100]); }); - it("paddingException(n) will not pad beyond n", function () { domainer.pad(0.1).addPaddingException(0, "key").addPaddingException(200); var domain = domainer.computeDomain([[0, 100]], scale); @@ -4086,7 +3274,6 @@ describe("Domainer", function () { domain = domainer.computeDomain([[0, 200]], scale); assert.notEqual(domain[1], 200, "unregistered paddingExceptions can be removed using boolean argument"); }); - it("paddingException(n) works on dates", function () { var a = new Date(2000, 5, 5); var b = new Date(2003, 0, 1); @@ -4098,7 +3285,6 @@ describe("Domainer", function () { assert.deepEqual(domain[0], a); assert.isTrue(b < domain[1]); }); - it("include(n) works an expected", function () { domainer.addIncludedValue(5); var domain = domainer.computeDomain([[0, 10]], scale); @@ -4107,19 +3293,16 @@ describe("Domainer", function () { assert.deepEqual(domain, [0, 5]); domain = domainer.computeDomain([[100, 200]], scale); assert.deepEqual(domain, [5, 200]); - domainer.addIncludedValue(-3).addIncludedValue(0).addIncludedValue(10, "key"); domain = domainer.computeDomain([[100, 200]], scale); assert.deepEqual(domain, [-3, 200]); domain = domainer.computeDomain([[0, 0]], scale); assert.deepEqual(domain, [-3, 10]); - domainer.removeIncludedValue("key"); domain = domainer.computeDomain([[100, 200]], scale); assert.deepEqual(domain, [-3, 200]); domain = domainer.computeDomain([[-100, -50]], scale); assert.deepEqual(domain, [-100, 5]); - domainer.addIncludedValue(10); domain = domainer.computeDomain([[-100, -50]], scale); assert.deepEqual(domain, [-100, 10], "unregistered includedValues can be added"); @@ -4127,7 +3310,6 @@ describe("Domainer", function () { domain = domainer.computeDomain([[-100, -50]], scale); assert.deepEqual(domain, [-100, 5], "unregistered includedValues can be removed with addOrRemove argument"); }); - it("include(n) works on dates", function () { var a = new Date(2000, 5, 4); var b = new Date(2000, 5, 5); @@ -4139,7 +3321,6 @@ describe("Domainer", function () { timeScale.domainer(domainer); assert.deepEqual(timeScale.domain(), [b, d]); }); - it("exceptions are setup properly on an area plot", function () { var xScale = new Plottable.Scale.Linear(); var yScale = new Plottable.Scale.Linear(); @@ -4150,7 +3331,6 @@ describe("Domainer", function () { r.project("x", "x", xScale); r.project("y", "y", yScale); r.renderTo(svg); - function getExceptions() { yScale.autoDomain(); var yDomain = yScale.domain(); @@ -4163,17 +3343,12 @@ describe("Domainer", function () { } return exceptions; } - assert.deepEqual(getExceptions(), [0], "initializing the plot adds a padding exception at 0"); - - // assert.deepEqual(getExceptions(), [], "Initially there are no padding exceptions"); r.project("y0", "y0", yScale); assert.deepEqual(getExceptions(), [], "projecting a non-constant y0 removes the padding exception"); r.project("y0", 0, yScale); assert.deepEqual(getExceptions(), [0], "projecting constant y0 adds the exception back"); - r.project("y0", function () { - return 5; - }, yScale); + r.project("y0", function () { return 5; }, yScale); assert.deepEqual(getExceptions(), [5], "projecting a different constant y0 removed the old exception and added a new one"); r.project("y0", "y0", yScale); assert.deepEqual(getExceptions(), [], "projecting a non-constant y0 removes the padding exception"); @@ -4183,9 +3358,7 @@ describe("Domainer", function () { }); }); -/// var assert = chai.assert; - describe("Coordinators", function () { describe("ScaleDomainCoordinator", function () { it("domains are coordinated", function () { @@ -4197,7 +3370,6 @@ describe("Coordinators", function () { assert.deepEqual(s1.domain(), [0, 100]); assert.deepEqual(s1.domain(), s2.domain()); assert.deepEqual(s1.domain(), s3.domain()); - s1.domain([-100, 5000]); assert.deepEqual(s1.domain(), [-100, 5000]); assert.deepEqual(s1.domain(), s2.domain()); @@ -4206,9 +3378,7 @@ describe("Coordinators", function () { }); }); -/// var assert = chai.assert; - describe("Scales", function () { it("Scale's copy() works correctly", function () { var testCallback = function (broadcaster) { @@ -4221,7 +3391,6 @@ describe("Scales", function () { assert.deepEqual(scale.range(), scaleCopy.range(), "Copied scale has the same range as the original."); assert.notDeepEqual(scale.broadcaster, scaleCopy.broadcaster, "Broadcasters are not copied over"); }); - it("Scale alerts listeners when its domain is updated", function () { var scale = new Plottable.Scale.Linear(); var callbackWasCalled = false; @@ -4232,18 +3401,15 @@ describe("Scales", function () { scale.broadcaster.registerListener(null, testCallback); scale.domain([0, 10]); assert.isTrue(callbackWasCalled, "The registered callback was called"); - scale.autoDomainAutomatically = true; scale.updateExtent("1", "x", [0.08, 9.92]); callbackWasCalled = false; scale.domainer(new Plottable.Domainer().nice()); assert.isTrue(callbackWasCalled, "The registered callback was called when nice() is used to set the domain"); - callbackWasCalled = false; scale.domainer(new Plottable.Domainer().pad()); assert.isTrue(callbackWasCalled, "The registered callback was called when padDomain() is used to set the domain"); }); - describe("autoranging behavior", function () { var data; var dataSource; @@ -4253,17 +3419,13 @@ describe("Scales", function () { dataSource = new Plottable.DataSource(data); scale = new Plottable.Scale.Linear(); }); - it("scale autoDomain flag is not overwritten without explicitly setting the domain", function () { - scale.updateExtent("1", "x", d3.extent(data, function (e) { - return e.foo; - })); + scale.updateExtent("1", "x", d3.extent(data, function (e) { return e.foo; })); scale.domainer(new Plottable.Domainer().pad().nice()); assert.isTrue(scale.autoDomainAutomatically, "the autoDomain flag is still set after autoranginging and padding and nice-ing"); scale.domain([0, 5]); assert.isFalse(scale.autoDomainAutomatically, "the autoDomain flag is false after domain explicitly set"); }); - it("scale autorange works as expected with single dataSource", function () { var svg = generateSVG(100, 100); var renderer = new Plottable.Abstract.Plot().dataSource(dataSource).project("x", "foo", scale).renderTo(svg); @@ -4273,7 +3435,6 @@ describe("Scales", function () { assert.deepEqual(scale.domain(), [0, 100], "scale domain was autoranged properly"); svg.remove(); }); - it("scale reference counting works as expected", function () { var svg1 = generateSVG(100, 100); var svg2 = generateSVG(100, 100); @@ -4286,35 +3447,25 @@ describe("Scales", function () { dataSource.data([{ foo: 10 }, { foo: 11 }]); assert.deepEqual(scale.domain(), [10, 11], "scale was still listening to dataSource after one perspective deregistered"); renderer2.project("x", "foo", otherScale); - - // "scale not listening to the dataSource after all perspectives removed" dataSource.data([{ foo: 99 }, { foo: 100 }]); assert.deepEqual(scale.domain(), [0, 1], "scale shows default values when all perspectives removed"); svg1.remove(); svg2.remove(); }); - it("scale perspectives can be removed appropriately", function () { assert.isTrue(scale.autoDomainAutomatically, "autoDomain enabled1"); - scale.updateExtent("1", "x", d3.extent(data, function (e) { - return e.foo; - })); - scale.updateExtent("2", "x", d3.extent(data, function (e) { - return e.bar; - })); + scale.updateExtent("1", "x", d3.extent(data, function (e) { return e.foo; })); + scale.updateExtent("2", "x", d3.extent(data, function (e) { return e.bar; })); assert.isTrue(scale.autoDomainAutomatically, "autoDomain enabled2"); assert.deepEqual(scale.domain(), [-20, 5], "scale domain includes both perspectives"); assert.isTrue(scale.autoDomainAutomatically, "autoDomain enabled3"); scale.removeExtent("1", "x"); assert.isTrue(scale.autoDomainAutomatically, "autoDomain enabled4"); assert.deepEqual(scale.domain(), [-20, 1], "only the bar accessor is active"); - scale.updateExtent("2", "x", d3.extent(data, function (e) { - return e.foo; - })); + scale.updateExtent("2", "x", d3.extent(data, function (e) { return e.foo; })); assert.isTrue(scale.autoDomainAutomatically, "autoDomain enabled5"); assert.deepEqual(scale.domain(), [0, 5], "the bar accessor was overwritten"); }); - it("should resize when a plot is removed", function () { var svg = generateSVG(400, 400); var ds1 = [{ x: 0, y: 0 }, { x: 1, y: 1 }]; @@ -4336,7 +3487,6 @@ describe("Scales", function () { svg.remove(); }); }); - describe("Quantitative Scales", function () { it("autorange defaults to [0, 1] if no perspectives set", function () { var scale = new Plottable.Scale.Linear(); @@ -4345,13 +3495,11 @@ describe("Scales", function () { assert.equal(d[0], 0); assert.equal(d[1], 1); }); - it("autorange defaults to [1, 10] on log scale", function () { var scale = new Plottable.Scale.Log(); scale.autoDomain(); assert.deepEqual(scale.domain(), [1, 10]); }); - it("domain can't include NaN or Infinity", function () { var scale = new Plottable.Scale.Linear(); scale.domain([0, 1]); @@ -4365,32 +3513,26 @@ describe("Scales", function () { assert.deepEqual(scale.domain(), [-1, 5], "Regular domains still accepted"); }); }); - describe("Ordinal Scales", function () { it("defaults to \"bands\" range type", function () { var scale = new Plottable.Scale.Ordinal(); assert.deepEqual(scale.rangeType(), "bands"); }); - it("rangeBand returns 0 when in \"points\" mode", function () { var scale = new Plottable.Scale.Ordinal().rangeType("points"); assert.deepEqual(scale.rangeType(), "points"); assert.deepEqual(scale.rangeBand(), 0); }); - it("rangeBand is updated when domain changes in \"bands\" mode", function () { var scale = new Plottable.Scale.Ordinal(); scale.rangeType("bands"); assert.deepEqual(scale.rangeType(), "bands"); scale.range([0, 2679]); - scale.domain([1, 2, 3, 4]); assert.deepEqual(scale.rangeBand(), 399); - scale.domain([1, 2, 3, 4, 5]); assert.deepEqual(scale.rangeBand(), 329); }); - it("rangeType triggers broadcast", function () { var scale = new Plottable.Scale.Ordinal(); var callbackWasCalled = false; @@ -4403,9 +3545,7 @@ describe("Scales", function () { assert.isTrue(callbackWasCalled, "The registered callback was called"); }); }); - it("OrdinalScale + BarPlot combo works as expected when the data is swapped", function () { - // This unit test taken from SLATE, see SLATE-163 a fix for SLATE-102 var xScale = new Plottable.Scale.Ordinal(); var yScale = new Plottable.Scale.Linear(); var dA = { x: "A", y: 2 }; @@ -4416,27 +3556,23 @@ describe("Scales", function () { assert.deepEqual(xScale.domain(), [], "before anchoring, the bar plot doesn't proxy data to the scale"); barPlot.renderTo(svg); assert.deepEqual(xScale.domain(), ["A", "B"], "after anchoring, the bar plot's data is on the scale"); - function iterateDataChanges() { var dataChanges = []; - for (var _i = 0; _i < (arguments.length - 0); _i++) { - dataChanges[_i] = arguments[_i + 0]; + for (var _i = 0; _i < arguments.length; _i++) { + dataChanges[_i - 0] = arguments[_i]; } dataChanges.forEach(function (dataChange) { barPlot.dataSource().data(dataChange); }); } - iterateDataChanges([], [dA, dB, dC], []); assert.lengthOf(xScale.domain(), 0); - iterateDataChanges([dA], [dB]); assert.lengthOf(xScale.domain(), 1); iterateDataChanges([], [dA, dB, dC]); assert.lengthOf(xScale.domain(), 3); svg.remove(); }); - describe("Color Scales", function () { it("accepts categorical string types and ordinal domain", function () { var scale = new Plottable.Scale.Color("10"); @@ -4446,7 +3582,6 @@ describe("Scales", function () { assert.equal("#2ca02c", scale.scale("maybe")); }); }); - describe("Interpolated Color Scales", function () { it("default scale uses reds and a linear scale type", function () { var scale = new Plottable.Scale.InterpolatedColor(); @@ -4455,14 +3590,12 @@ describe("Scales", function () { assert.equal("#feb24c", scale.scale(8)); assert.equal("#b10026", scale.scale(16)); }); - it("linearly interpolates colors in L*a*b color space", function () { var scale = new Plottable.Scale.InterpolatedColor("reds"); scale.domain([0, 1]); assert.equal("#b10026", scale.scale(1)); assert.equal("#d9151f", scale.scale(0.9)); }); - it("accepts array types with color hex values", function () { var scale = new Plottable.Scale.InterpolatedColor(["#000", "#FFF"]); scale.domain([0, 16]); @@ -4470,7 +3603,6 @@ describe("Scales", function () { assert.equal("#ffffff", scale.scale(16)); assert.equal("#777777", scale.scale(8)); }); - it("accepts array types with color names", function () { var scale = new Plottable.Scale.InterpolatedColor(["black", "white"]); scale.domain([0, 16]); @@ -4478,7 +3610,6 @@ describe("Scales", function () { assert.equal("#ffffff", scale.scale(16)); assert.equal("#777777", scale.scale(8)); }); - it("overflow scale values clamp to range", function () { var scale = new Plottable.Scale.InterpolatedColor(["black", "white"]); scale.domain([0, 16]); @@ -4487,7 +3618,6 @@ describe("Scales", function () { assert.equal("#000000", scale.scale(-100)); assert.equal("#ffffff", scale.scale(100)); }); - it("can be converted to a different range", function () { var scale = new Plottable.Scale.InterpolatedColor(["black", "white"]); scale.domain([0, 16]); @@ -4496,20 +3626,17 @@ describe("Scales", function () { scale.colorRange("reds"); assert.equal("#b10026", scale.scale(16)); }); - it("can be converted to a different scale type", function () { var scale = new Plottable.Scale.InterpolatedColor(["black", "white"]); scale.domain([0, 16]); assert.equal("#000000", scale.scale(0)); assert.equal("#ffffff", scale.scale(16)); assert.equal("#777777", scale.scale(8)); - scale.scaleType("log"); assert.equal("#000000", scale.scale(0)); assert.equal("#ffffff", scale.scale(16)); assert.equal("#e3e3e3", scale.scale(8)); }); - it("doesn't use a domainer", function () { var scale = new Plottable.Scale.InterpolatedColor(["black", "white"]); var startDomain = scale.domain(); @@ -4525,109 +3652,74 @@ describe("Scales", function () { beforeEach(function () { scale = new Plottable.Scale.ModifiedLog(base); }); - it("is an increasing, continuous function that can go negative", function () { d3.range(-base * 2, base * 2, base / 20).forEach(function (x) { - // increasing assert.operator(scale.scale(x - epsilon), "<", scale.scale(x)); assert.operator(scale.scale(x), "<", scale.scale(x + epsilon)); - - // continuous assert.closeTo(scale.scale(x - epsilon), scale.scale(x), epsilon); assert.closeTo(scale.scale(x), scale.scale(x + epsilon), epsilon); }); assert.closeTo(scale.scale(0), 0, epsilon); }); - it("is close to log() for large values", function () { [10, 100, 23103.4, 5].forEach(function (x) { assert.closeTo(scale.scale(x), Math.log(x) / Math.log(10), 0.1); }); }); - it("x = invert(scale(x))", function () { [0, 1, base, 100, 0.001, -1, -0.3, -base, base - 0.001].forEach(function (x) { assert.closeTo(x, scale.invert(scale.scale(x)), epsilon); assert.closeTo(x, scale.scale(scale.invert(x)), epsilon); }); }); - it("domain defaults to [0, 1]", function () { scale = new Plottable.Scale.ModifiedLog(base); assert.deepEqual(scale.domain(), [0, 1]); }); - it("works with a domainer", function () { scale.updateExtent("1", "x", [0, base * 2]); var domain = scale.domain(); scale.domainer(new Plottable.Domainer().pad(0.1)); assert.operator(scale.domain()[0], "<", domain[0]); assert.operator(domain[1], "<", scale.domain()[1]); - scale.domainer(new Plottable.Domainer().nice()); assert.operator(scale.domain()[0], "<=", domain[0]); assert.operator(domain[1], "<=", scale.domain()[1]); - scale = new Plottable.Scale.ModifiedLog(base); scale.domainer(new Plottable.Domainer()); assert.deepEqual(scale.domain(), [0, 1]); }); - it("gives reasonable values for ticks()", function () { scale.updateExtent("1", "x", [0, base / 2]); var ticks = scale.ticks(); assert.operator(ticks.length, ">", 0); - scale.updateExtent("1", "x", [-base * 2, base * 2]); ticks = scale.ticks(); - var beforePivot = ticks.filter(function (x) { - return x <= -base; - }); - var afterPivot = ticks.filter(function (x) { - return base <= x; - }); - var betweenPivots = ticks.filter(function (x) { - return -base < x && x < base; - }); + var beforePivot = ticks.filter(function (x) { return x <= -base; }); + var afterPivot = ticks.filter(function (x) { return base <= x; }); + var betweenPivots = ticks.filter(function (x) { return -base < x && x < base; }); assert.operator(beforePivot.length, ">", 0, "should be ticks before -base"); assert.operator(afterPivot.length, ">", 0, "should be ticks after base"); assert.operator(betweenPivots.length, ">", 0, "should be ticks between -base and base"); }); - it("works on inverted domain", function () { scale.updateExtent("1", "x", [200, -100]); var range = scale.range(); assert.closeTo(scale.scale(-100), range[1], epsilon); assert.closeTo(scale.scale(200), range[0], epsilon); var a = [-100, -10, -3, 0, 1, 3.64, 50, 60, 200]; - var b = a.map(function (x) { - return scale.scale(x); - }); - - // should be decreasing function; reverse is sorted - assert.deepEqual(b.slice().reverse(), b.slice().sort(function (x, y) { - return x - y; - })); - + var b = a.map(function (x) { return scale.scale(x); }); + assert.deepEqual(b.slice().reverse(), b.slice().sort(function (x, y) { return x - y; })); var ticks = scale.ticks(); - assert.deepEqual(ticks, ticks.slice().sort(function (x, y) { - return x - y; - }), "ticks should be sorted"); + assert.deepEqual(ticks, ticks.slice().sort(function (x, y) { return x - y; }), "ticks should be sorted"); assert.deepEqual(ticks, Plottable.Util.Methods.uniqNumbers(ticks), "ticks should not be repeated"); - var beforePivot = ticks.filter(function (x) { - return x <= -base; - }); - var afterPivot = ticks.filter(function (x) { - return base <= x; - }); - var betweenPivots = ticks.filter(function (x) { - return -base < x && x < base; - }); + var beforePivot = ticks.filter(function (x) { return x <= -base; }); + var afterPivot = ticks.filter(function (x) { return base <= x; }); + var betweenPivots = ticks.filter(function (x) { return -base < x && x < base; }); assert.operator(beforePivot.length, ">", 0, "should be ticks before -base"); assert.operator(afterPivot.length, ">", 0, "should be ticks after base"); assert.operator(betweenPivots.length, ">", 0, "should be ticks between -base and base"); }); - it("ticks() is always non-empty", function () { [[2, 9], [0, 1], [1, 2], [0.001, 0.01], [-0.1, 0.1], [-3, -2]].forEach(function (domain) { scale.updateExtent("1", "x", domain); @@ -4638,15 +3730,12 @@ describe("Scales", function () { }); }); -/// var assert = chai.assert; - describe("TimeScale tests", function () { it("parses reasonable formats for dates", function () { var scale = new Plottable.Scale.Time(); var firstDate = new Date(2014, 9, 1, 0, 0, 0, 0).valueOf(); var secondDate = new Date(2014, 10, 1, 0, 0, 0).valueOf(); - function checkDomain(domain) { scale.domain(domain); var time1 = scale.domain()[0].valueOf(); @@ -4658,49 +3747,34 @@ describe("TimeScale tests", function () { checkDomain(["October 1, 2014", "November 1, 2014"]); checkDomain(["Oct 1, 2014", "Nov 1, 2014"]); }); - it("tickInterval produces correct number of ticks", function () { var scale = new Plottable.Scale.Time(); - - // 100 year span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2100, 0, 1, 0, 0, 0, 0)]); var ticks = scale.tickInterval(d3.time.year); assert.equal(ticks.length, 101, "generated correct number of ticks"); - - // 1 year span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 11, 31, 0, 0, 0, 0)]); ticks = scale.tickInterval(d3.time.month); assert.equal(ticks.length, 12, "generated correct number of ticks"); ticks = scale.tickInterval(d3.time.month, 3); assert.equal(ticks.length, 4, "generated correct number of ticks"); - - // 1 month span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 1, 1, 0, 0, 0, 0)]); ticks = scale.tickInterval(d3.time.day); assert.equal(ticks.length, 32, "generated correct number of ticks"); - - // 1 day span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 23, 0, 0, 0)]); ticks = scale.tickInterval(d3.time.hour); assert.equal(ticks.length, 24, "generated correct number of ticks"); - - // 1 hour span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 1, 0, 0, 0)]); ticks = scale.tickInterval(d3.time.minute); assert.equal(ticks.length, 61, "generated correct number of ticks"); ticks = scale.tickInterval(d3.time.minute, 10); assert.equal(ticks.length, 7, "generated correct number of ticks"); - - // 1 minute span scale.domain([new Date(2000, 0, 1, 0, 0, 0, 0), new Date(2000, 0, 1, 0, 1, 0, 0)]); ticks = scale.tickInterval(d3.time.second); assert.equal(ticks.length, 61, "generated correct number of ticks"); }); }); -/// var assert = chai.assert; - describe("Util.DOM", function () { it("getBBox works properly", function () { var svg = generateSVG(); @@ -4710,58 +3784,47 @@ describe("Util.DOM", function () { assert.deepEqual(bb1, bb2); svg.remove(); }); - describe("getElementWidth, getElementHeight", function () { it("can get a plain element's size", function () { var parent = getSVGParent(); parent.style("width", "300px"); parent.style("height", "200px"); var parentElem = parent[0][0]; - var width = Plottable.Util.DOM.getElementWidth(parentElem); assert.equal(width, 300, "measured width matches set width"); var height = Plottable.Util.DOM.getElementHeight(parentElem); assert.equal(height, 200, "measured height matches set height"); }); - it("can get the svg's size", function () { var svg = generateSVG(450, 120); var svgElem = svg[0][0]; - var width = Plottable.Util.DOM.getElementWidth(svgElem); assert.equal(width, 450, "measured width matches set width"); var height = Plottable.Util.DOM.getElementHeight(svgElem); assert.equal(height, 120, "measured height matches set height"); svg.remove(); }); - it("can accept multiple units and convert to pixels", function () { var parent = getSVGParent(); var parentElem = parent[0][0]; var child = parent.append("div"); var childElem = child[0][0]; - parent.style("width", "200px"); parent.style("height", "50px"); assert.equal(Plottable.Util.DOM.getElementWidth(parentElem), 200, "width is correct"); assert.equal(Plottable.Util.DOM.getElementHeight(parentElem), 50, "height is correct"); - child.style("width", "20px"); child.style("height", "10px"); assert.equal(Plottable.Util.DOM.getElementWidth(childElem), 20, "width is correct"); assert.equal(Plottable.Util.DOM.getElementHeight(childElem), 10, "height is correct"); - child.style("width", "100%"); child.style("height", "100%"); assert.equal(Plottable.Util.DOM.getElementWidth(childElem), 200, "width is correct"); assert.equal(Plottable.Util.DOM.getElementHeight(childElem), 50, "height is correct"); - child.style("width", "50%"); child.style("height", "50%"); assert.equal(Plottable.Util.DOM.getElementWidth(childElem), 100, "width is correct"); assert.equal(Plottable.Util.DOM.getElementHeight(childElem), 25, "height is correct"); - - // reset test page DOM parent.style("width", "auto"); parent.style("height", "auto"); child.remove(); @@ -4769,9 +3832,7 @@ describe("Util.DOM", function () { }); }); -/// var assert = chai.assert; - describe("Formatters", function () { describe("fixed", function () { it("shows exactly [precision] digits", function () { @@ -4783,20 +3844,17 @@ describe("Formatters", function () { result = fixed3(1.2345); assert.strictEqual(result, "", "changed values are not shown (get turned into empty strings)"); }); - it("precision can be changed", function () { var fixed2 = Plottable.Formatters.fixed(2); var result = fixed2(1); assert.strictEqual(result, "1.00", "formatter was changed to show only two decimal places"); }); - it("can be set to show rounded values", function () { var fixed3 = Plottable.Formatters.fixed(3, false); var result = fixed3(1.2349); assert.strictEqual(result, "1.235", "long values are rounded correctly"); }); }); - describe("general", function () { it("formats number to show at most [precision] digits", function () { var general = Plottable.Formatters.general(); @@ -4807,7 +3865,6 @@ describe("Formatters", function () { result = general(1.2345); assert.strictEqual(result, "", "(changed) values with more than three decimal places are not shown"); }); - it("stringifies non-number values", function () { var general = Plottable.Formatters.general(); var result = general("blargh"); @@ -4815,7 +3872,6 @@ describe("Formatters", function () { result = general(null); assert.strictEqual(result, "null", "non-number inputs are stringified"); }); - it("throws an error on strange precision", function () { assert.throws(function () { var general = Plottable.Formatters.general(-1); @@ -4827,7 +3883,6 @@ describe("Formatters", function () { }); }); }); - describe("identity", function () { it("stringifies inputs", function () { var identity = Plottable.Formatters.identity(); @@ -4841,7 +3896,6 @@ describe("Formatters", function () { assert.strictEqual(result, "undefined", "formats undefined"); }); }); - describe("currency", function () { it("uses reasonable defaults", function () { var currencyFormatter = Plottable.Formatters.currency(); @@ -4849,24 +3903,19 @@ describe("Formatters", function () { assert.strictEqual(result.charAt(0), "$", "defaults to $ for currency symbol"); var decimals = result.substring(result.indexOf(".") + 1, result.length); assert.strictEqual(decimals.length, 2, "defaults to 2 decimal places"); - result = currencyFormatter(-1); assert.strictEqual(result.charAt(0), "-", "prefixes negative values with \"-\""); assert.strictEqual(result.charAt(1), "$", "places the currency symbol after the negative sign"); }); - it("can change the type and position of the currency symbol", function () { var centsFormatter = Plottable.Formatters.currency(0, "c", false); var result = centsFormatter(1); assert.strictEqual(result.charAt(result.length - 1), "c", "The specified currency symbol was appended"); }); }); - describe("time", function () { it("uses reasonable defaults", function () { var timeFormatter = Plottable.Formatters.time(); - - // year, month, day, hours, minutes, seconds, milliseconds var result = timeFormatter(new Date(2000, 0, 1, 0, 0, 0, 0)); assert.strictEqual(result, "2000", "only the year was displayed"); result = timeFormatter(new Date(2000, 2, 1, 0, 0, 0, 0)); @@ -4883,14 +3932,12 @@ describe("Formatters", function () { assert.strictEqual(result, ".950", "milliseconds was displayed"); }); }); - describe("percentage", function () { it("uses reasonable defaults", function () { var percentFormatter = Plottable.Formatters.percentage(); var result = percentFormatter(1); assert.strictEqual(result, "100%", "the value was multiplied by 100, a percent sign was appended, and no decimal places are shown by default"); }); - it("can handle float imprecision", function () { var percentFormatter = Plottable.Formatters.percentage(); var result = percentFormatter(0.07); @@ -4900,12 +3947,9 @@ describe("Formatters", function () { assert.strictEqual(result2, "0.35%", "works even if multiplying by 100 does not make it an integer"); }); }); - describe("time", function () { it("uses reasonable defaults", function () { var timeFormatter = Plottable.Formatters.time(); - - // year, month, day, hours, minutes, seconds, milliseconds var result = timeFormatter(new Date(2000, 0, 1, 0, 0, 0, 0)); assert.strictEqual(result, "2000", "only the year was displayed"); result = timeFormatter(new Date(2000, 2, 1, 0, 0, 0, 0)); @@ -4922,7 +3966,6 @@ describe("Formatters", function () { assert.strictEqual(result, ".950", "milliseconds was displayed"); }); }); - describe("SISuffix", function () { it("shortens long numbers", function () { var lnFormatter = Plottable.Formatters.siSuffix(); @@ -4934,14 +3977,12 @@ describe("Formatters", function () { assert.operator(result.length, "<=", 5, "small number was formatted to a short string"); }); }); - describe("relativeDate", function () { it("uses reasonable defaults", function () { var relativeDateFormatter = Plottable.Formatters.relativeDate(); var result = relativeDateFormatter(7 * Plottable.MILLISECONDS_IN_ONE_DAY); assert.strictEqual(result, "7", "7 day difference from epoch, incremented by days, no suffix"); }); - it("resulting value is difference from base value", function () { var relativeDateFormatter = Plottable.Formatters.relativeDate(5 * Plottable.MILLISECONDS_IN_ONE_DAY); var result = relativeDateFormatter(9 * Plottable.MILLISECONDS_IN_ONE_DAY); @@ -4949,17 +3990,14 @@ describe("Formatters", function () { var result = relativeDateFormatter(Plottable.MILLISECONDS_IN_ONE_DAY); assert.strictEqual(result, "-4", "4 days less from base value"); }); - it("can increment by different time types (hours, minutes)", function () { var hoursRelativeDateFormatter = Plottable.Formatters.relativeDate(0, Plottable.MILLISECONDS_IN_ONE_DAY / 24); var result = hoursRelativeDateFormatter(3 * Plottable.MILLISECONDS_IN_ONE_DAY); assert.strictEqual(result, "72", "72 hour difference from epoch"); - var minutesRelativeDateFormatter = Plottable.Formatters.relativeDate(0, Plottable.MILLISECONDS_IN_ONE_DAY / (24 * 60)); var result = minutesRelativeDateFormatter(3 * Plottable.MILLISECONDS_IN_ONE_DAY); assert.strictEqual(result, "4320", "4320 minute difference from epoch"); }); - it("can append a suffix", function () { var relativeDateFormatter = Plottable.Formatters.relativeDate(0, Plottable.MILLISECONDS_IN_ONE_DAY, "days"); var result = relativeDateFormatter(7 * Plottable.MILLISECONDS_IN_ONE_DAY); @@ -4968,9 +4006,7 @@ describe("Formatters", function () { }); }); -/// var assert = chai.assert; - describe("IDCounter", function () { it("IDCounter works as expected", function () { var i = new Plottable.Util.IDCounter(); @@ -4985,9 +4021,7 @@ describe("IDCounter", function () { }); }); -/// var assert = chai.assert; - describe("StrictEqualityAssociativeArray", function () { it("StrictEqualityAssociativeArray works as expected", function () { var s = new Plottable.Util.StrictEqualityAssociativeArray(); @@ -5012,7 +4046,6 @@ describe("StrictEqualityAssociativeArray", function () { assert.equal(s.get(o2), "baz"); assert.equal(s.get("3"), "ball"); }); - it("Array-level operations (retrieve keys, vals, and map)", function () { var s = new Plottable.Util.StrictEqualityAssociativeArray(); s.set(2, "foo"); @@ -5020,36 +4053,28 @@ describe("StrictEqualityAssociativeArray", function () { s.set(4, "baz"); assert.deepEqual(s.values(), ["foo", "bar", "baz"]); assert.deepEqual(s.keys(), [2, 3, 4]); - assert.deepEqual(s.map(function (k, v, i) { - return [k, v, i]; - }), [[2, "foo", 0], [3, "bar", 1], [4, "baz", 2]]); + assert.deepEqual(s.map(function (k, v, i) { return [k, v, i]; }), [[2, "foo", 0], [3, "bar", 1], [4, "baz", 2]]); }); }); -/// var assert = chai.assert; - describe("CachingCharacterMeasurer", function () { var g; var measurer; var svg; - beforeEach(function () { svg = generateSVG(100, 100); g = svg.append("g"); measurer = new Plottable.Util.Text.CachingCharacterMeasurer(g.append("text")); }); - afterEach(function () { svg.remove(); }); - it("empty string has non-zero size", function () { var a = measurer.measure("x x").width; var b = measurer.measure("xx").width; assert.operator(a, ">", b, "'x x' is longer than 'xx'"); }); - it("should repopulate cache if it changes size and clear() is called", function () { var a = measurer.measure("x").width; g.style("font-size", "40px"); @@ -5059,7 +4084,6 @@ describe("CachingCharacterMeasurer", function () { var c = measurer.measure("x").width; assert.operator(a, "<", c, "cache reset after font size changed"); }); - it("multiple spaces take up same area as one space", function () { var a = measurer.measure("x x").width; var b = measurer.measure("x \t \n x").width; @@ -5067,9 +4091,7 @@ describe("CachingCharacterMeasurer", function () { }); }); -/// var assert = chai.assert; - describe("Cache", function () { var callbackCalled = false; var f = function (s) { @@ -5077,12 +4099,10 @@ describe("Cache", function () { return s + s; }; var cache; - beforeEach(function () { callbackCalled = false; cache = new Plottable.Util.Cache(f); }); - it("Doesn't call its function if it already called", function () { assert.equal(cache.get("hello"), "hellohello"); assert.isTrue(callbackCalled); @@ -5090,7 +4110,6 @@ describe("Cache", function () { assert.equal(cache.get("hello"), "hellohello"); assert.isFalse(callbackCalled); }); - it("Clears its cache when .clear() is called", function () { var prefix = "hello"; cache = new Plottable.Util.Cache(function (s) { @@ -5107,7 +4126,6 @@ describe("Cache", function () { assert.equal(cache.get("world"), "holaworld"); assert.isTrue(callbackCalled); }); - it("Doesn't clear the cache when canonicalKey doesn't change", function () { cache = new Plottable.Util.Cache(f, "x"); assert.equal(cache.get("hello"), "hellohello"); @@ -5117,7 +4135,6 @@ describe("Cache", function () { assert.equal(cache.get("hello"), "hellohello"); assert.isFalse(callbackCalled); }); - it("Clears the cache when canonicalKey changes", function () { var prefix = "hello"; cache = new Plottable.Util.Cache(function (s) { @@ -5132,12 +4149,9 @@ describe("Cache", function () { cache.get("world"); assert.isTrue(callbackCalled); }); - it("uses valueEq to check if it should clear", function () { var decider = true; - cache = new Plottable.Util.Cache(f, "x", function (a, b) { - return decider; - }); + cache = new Plottable.Util.Cache(f, "x", function (a, b) { return decider; }); cache.get("hello"); assert.isTrue(callbackCalled); cache.clear(); @@ -5151,7 +4165,6 @@ describe("Cache", function () { }); }); -/// var assert = chai.assert; describe("Util.Text", function () { it("getTruncatedText works properly", function () { @@ -5165,58 +4178,46 @@ describe("Util.Text", function () { assert.equal(partialText, "hello...", "text truncated"); var tinyText = Plottable.Util.Text.getTruncatedText("hellom world!", 5, measure); assert.equal(tinyText, "", "empty string for tiny text"); - svg.remove(); }); - describe("_addEllipsesToLine", function () { var svg; var measure; var e; var textSelection; - before(function () { svg = generateSVG(); textSelection = svg.append("text"); measure = Plottable.Util.Text.getTextMeasurer(textSelection); - e = function (text, width) { - return Plottable.Util.Text._addEllipsesToLine(text, width, measure); - }; + e = function (text, width) { return Plottable.Util.Text._addEllipsesToLine(text, width, measure); }; }); it("works on an empty string", function () { assert.equal(e("", 200), "...", "produced \"...\" with plenty of space"); }); - it("works as expected when given no width", function () { assert.equal(e("this wont fit", 0), "", "returned empty string when width is 0"); }); - it("works as expected when given only one periods worth of space", function () { var w = measure(".").width; assert.equal(e("this won't fit", w), ".", "returned a single period"); }); - it("works as expected with plenty of space", function () { assert.equal(e("this will fit", 400), "this will fit..."); }); - it("works as expected with insufficient space", function () { var w = measure("this won't fit").width; assert.equal(e("this won't fit", w), "this won't..."); }); - it("handles spaces intelligently", function () { var spacey = "this xx"; var w = measure(spacey).width - 1; assert.equal(e(spacey, w), "this..."); }); - after(function () { assert.lengthOf(svg.node().childNodes, 0, "this was all without side-effects"); svg.remove(); }); }); - describe("writeText", function () { it("behaves appropriately when there is too little height and width to fit any text", function () { var svg = generateSVG(); @@ -5228,7 +4229,6 @@ describe("Util.Text", function () { assert.isFalse(results.textFits, "measurement mode: text doesn't fit"); assert.equal(0, results.usedWidth, "measurement mode: no width used"); assert.equal(0, results.usedHeight, "measurement mode: no height used"); - var writeOptions = { g: svg, xAlign: "center", yAlign: "center" }; results = Plottable.Util.Text.writeText("hello world", width, height, measure, true, writeOptions); assert.isFalse(results.textFits, "write mode: text doesn't fit"); @@ -5238,7 +4238,6 @@ describe("Util.Text", function () { assert.lengthOf(svg.selectAll("text")[0], 0, "no text was written"); svg.remove(); }); - it("behaves appropriately when there is plenty of width but too little height to fit text", function () { var svg = generateSVG(); var width = 500; @@ -5249,7 +4248,6 @@ describe("Util.Text", function () { assert.isFalse(results.textFits, "measurement mode: text doesn't fit"); assert.equal(0, results.usedWidth, "measurement mode: no width used"); assert.equal(0, results.usedHeight, "measurement mode: no height used"); - var writeOptions = { g: svg, xAlign: "center", yAlign: "center" }; results = Plottable.Util.Text.writeText("hello world", width, height, measure, true, writeOptions); assert.isFalse(results.textFits, "write mode: text doesn't fit"); @@ -5260,13 +4258,11 @@ describe("Util.Text", function () { svg.remove(); }); }); - describe("getTextMeasurer", function () { var svg; var measurer; var canonicalBB; var canonicalResult; - before(function () { svg = generateSVG(200, 200); var t = svg.append("text"); @@ -5276,7 +4272,6 @@ describe("Util.Text", function () { t.text("bla bla bla"); measurer = Plottable.Util.Text.getTextMeasurer(t); }); - it("works on empty string", function () { var result = measurer(""); assert.deepEqual(result, { width: 0, height: 0 }, "empty string has 0 width and height"); @@ -5289,13 +4284,11 @@ describe("Util.Text", function () { svg.remove(); }); }); - describe("writeLine", function () { var svg; var g; var text = "hello world ARE YOU THERE?"; var hideResults = true; - describe("writeLineHorizontally", function () { it("writes no text if there is insufficient space", function () { svg = generateSVG(20, 20); @@ -5307,7 +4300,6 @@ describe("Util.Text", function () { assert.equal(g.text(), "", "no text written"); svg.remove(); }); - it("performs basic functionality and defaults to left, top", function () { svg = generateSVG(400, 400); g = svg.append("g"); @@ -5330,7 +4322,6 @@ describe("Util.Text", function () { var bb = Plottable.Util.DOM.getBBox(textEl); var x = bb.x + Plottable.Util.DOM.translate(g.select("g"))[0] + bb.width / 2; var y = bb.y + Plottable.Util.DOM.translate(g.select("g"))[1] + bb.height / 2; - if (hideResults) { svg.remove(); } @@ -5344,13 +4335,11 @@ describe("Util.Text", function () { var bb = Plottable.Util.DOM.getBBox(textEl); var x = bb.x + Plottable.Util.DOM.translate(g.select("g"))[0] + bb.width; var y = bb.y + Plottable.Util.DOM.translate(g.select("g"))[1] + bb.height; - if (hideResults) { svg.remove(); } ; }); - it("throws an error if there's too little space", function () { svg = generateSVG(20, 20); g = svg.append("g"); @@ -5360,14 +4349,12 @@ describe("Util.Text", function () { ; }); }); - describe("writeLineVertically", function () { it("performs basic functionality and defaults to right, left, top", function () { svg = generateSVG(60, 400); g = svg.append("g"); var wh = Plottable.Util.Text.writeLineVertically(text, g, 60, 400); var bb = Plottable.Util.DOM.getBBox(g.select("g")); - if (hideResults) { svg.remove(); } @@ -5403,7 +4390,6 @@ describe("Util.Text", function () { } ; }); - it("left, center, center", function () { svg = generateSVG(60, 400); g = svg.append("g"); @@ -5413,7 +4399,6 @@ describe("Util.Text", function () { } ; }); - it("left, right, bottom", function () { svg = generateSVG(60, 400); g = svg.append("g"); @@ -5427,16 +4412,13 @@ describe("Util.Text", function () { }); }); -/// var assert = chai.assert; - describe("Util.s", function () { it("inRange works correct", function () { assert.isTrue(Plottable.Util.Methods.inRange(0, -1, 1), "basic functionality works"); assert.isTrue(Plottable.Util.Methods.inRange(0, 0, 1), "it is a closed interval"); assert.isTrue(!Plottable.Util.Methods.inRange(0, 1, 2), "returns false when false"); }); - it("sortedIndex works properly", function () { var a = [1, 2, 3, 4, 5]; var si = Plottable.Util.OpenSource.sortedIndex; @@ -5444,34 +4426,24 @@ describe("Util.s", function () { assert.equal(si(6, a), a.length, "returns a.length when val >= arr[arr.length-1]"); assert.equal(si(1.5, a), 1, "returns 1 when val is between the first and second elements"); }); - it("accessorize works properly", function () { var datum = { "foo": 2, "bar": 3, "key": 4 }; - - var f = function (d, i, m) { - return d + i; - }; + var f = function (d, i, m) { return d + i; }; var a1 = Plottable.Util.Methods._accessorize(f); assert.equal(f, a1, "function passes through accessorize unchanged"); - var a2 = Plottable.Util.Methods._accessorize("key"); assert.equal(a2(datum, 0, null), 4, "key accessor works appropriately"); - var a3 = Plottable.Util.Methods._accessorize("#aaaa"); assert.equal(a3(datum, 0, null), "#aaaa", "strings beginning with # are returned as final value"); - var a4 = Plottable.Util.Methods._accessorize(33); assert.equal(a4(datum, 0, null), 33, "numbers are return as final value"); - var a5 = Plottable.Util.Methods._accessorize(datum); assert.equal(a5(datum, 0, null), datum, "objects are return as final value"); }); - it("uniq works as expected", function () { var strings = ["foo", "bar", "foo", "foo", "baz", "bam"]; assert.deepEqual(Plottable.Util.Methods.uniq(strings), ["foo", "bar", "baz", "bam"]); }); - it("objEq works as expected", function () { assert.isTrue(Plottable.Util.Methods.objEq({}, {})); assert.isTrue(Plottable.Util.Methods.objEq({ a: 5 }, { a: 5 })); @@ -5482,9 +4454,7 @@ describe("Util.s", function () { }); }); -/// var assert = chai.assert; - function makeFakeEvent(x, y) { return { dx: 0, @@ -5500,7 +4470,6 @@ function makeFakeEvent(x, y) { altKey: false }; } - function fakeDragSequence(anyedInteraction, startX, startY, endX, endY) { anyedInteraction._dragstart(); d3.event = makeFakeEvent(startX, startY); @@ -5510,26 +4479,19 @@ function fakeDragSequence(anyedInteraction, startX, startY, endX, endY) { anyedInteraction._dragend(); d3.event = null; } - describe("Interactions", function () { describe("PanZoomInteraction", function () { it("Pans properly", function () { - // The only difference between pan and zoom is internal to d3 - // Simulating zoom events is painful, so panning will suffice here var xScale = new Plottable.Scale.Linear().domain([0, 11]); var yScale = new Plottable.Scale.Linear().domain([11, 0]); - var svg = generateSVG(); var dataset = makeLinearSeries(11); var renderer = new Plottable.Plot.Scatter(dataset, xScale, yScale); renderer.renderTo(svg); - var xDomainBefore = xScale.domain(); var yDomainBefore = yScale.domain(); - var interaction = new Plottable.Interaction.PanZoom(renderer, xScale, yScale); interaction.registerWithComponent(); - var hb = renderer.element.select(".hit-box").node(); var dragDistancePixelX = 10; var dragDistancePixelY = 20; @@ -5537,30 +4499,23 @@ describe("Interactions", function () { dx: dragDistancePixelX, dy: dragDistancePixelY }); - var xDomainAfter = xScale.domain(); var yDomainAfter = yScale.domain(); - assert.notDeepEqual(xDomainAfter, xDomainBefore, "x domain was changed by panning"); assert.notDeepEqual(yDomainAfter, yDomainBefore, "y domain was changed by panning"); - function getSlope(scale) { var range = scale.range(); var domain = scale.domain(); return (domain[1] - domain[0]) / (range[1] - range[0]); } ; - var expectedXDragChange = -dragDistancePixelX * getSlope(xScale); var expectedYDragChange = -dragDistancePixelY * getSlope(yScale); - assert.closeTo(xDomainAfter[0] - xDomainBefore[0], expectedXDragChange, 1, "x domain changed by the correct amount"); assert.closeTo(yDomainAfter[0] - yDomainBefore[0], expectedYDragChange, 1, "y domain changed by the correct amount"); - svg.remove(); }); }); - describe("XYDragBoxInteraction", function () { var svgWidth = 400; var svgHeight = 400; @@ -5570,12 +4525,10 @@ describe("Interactions", function () { var yScale; var renderer; var interaction; - var dragstartX = 20; var dragstartY = svgHeight - 100; var dragendX = 100; var dragendY = svgHeight - 20; - before(function () { svg = generateSVG(svgWidth, svgHeight); dataset = new Plottable.DataSource(makeLinearSeries(10)); @@ -5586,14 +4539,12 @@ describe("Interactions", function () { interaction = new Plottable.Interaction.XYDragBox(renderer); interaction.registerWithComponent(); }); - afterEach(function () { interaction.dragstart(null); interaction.drag(null); interaction.dragend(null); interaction.clearBox(); }); - it("All callbacks are notified with appropriate data on drag", function () { var timesCalled = 0; interaction.dragstart(function (a) { @@ -5605,7 +4556,7 @@ describe("Interactions", function () { timesCalled++; var expectedStart = { x: dragstartX, - y: dragstartY + y: dragstartY, }; var expectedEnd = { x: dragendX, @@ -5614,13 +4565,9 @@ describe("Interactions", function () { assert.deepEqual(a, expectedStart, "areaCallback was passed the correct starting point"); assert.deepEqual(b, expectedEnd, "areaCallback was passed the correct ending point"); }); - - // fake a drag event fakeDragSequence(interaction, dragstartX, dragstartY, dragendX, dragendY); - assert.equal(timesCalled, 2, "drag callbacks are called twice"); }); - it("Highlights and un-highlights areas appropriately", function () { fakeDragSequence(interaction, dragstartX, dragstartY, dragendX, dragendY); var dragBoxClass = "." + Plottable.Interaction.XYDragBox.CLASS_DRAG_BOX; @@ -5631,17 +4578,14 @@ describe("Interactions", function () { assert.deepEqual(actualStartPosition, expectedStartPosition, "highlighted box is positioned correctly"); assert.equal(parseFloat(dragBox.attr("width")), Math.abs(dragstartX - dragendX), "highlighted box has correct width"); assert.equal(parseFloat(dragBox.attr("height")), Math.abs(dragstartY - dragendY), "highlighted box has correct height"); - interaction.clearBox(); var boxGone = dragBox.attr("width") === "0" && dragBox.attr("height") === "0"; assert.isTrue(boxGone, "highlighted box disappears when clearBox is called"); }); - after(function () { svg.remove(); }); }); - describe("YDragBoxInteraction", function () { var svgWidth = 400; var svgHeight = 400; @@ -5651,12 +4595,10 @@ describe("Interactions", function () { var yScale; var renderer; var interaction; - var dragstartX = 20; var dragstartY = svgHeight - 100; var dragendX = 100; var dragendY = svgHeight - 20; - before(function () { svg = generateSVG(svgWidth, svgHeight); dataset = new Plottable.DataSource(makeLinearSeries(10)); @@ -5667,14 +4609,12 @@ describe("Interactions", function () { interaction = new Plottable.Interaction.YDragBox(renderer); interaction.registerWithComponent(); }); - afterEach(function () { interaction.dragstart(null); interaction.drag(null); interaction.dragend(null); interaction.clearBox(); }); - it("All callbacks are notified with appropriate data when a drag finishes", function () { var timesCalled = 0; interaction.dragstart(function (a) { @@ -5689,13 +4629,9 @@ describe("Interactions", function () { assert.deepEqual(a.y, expectedStartY); assert.deepEqual(b.y, expectedEndY); }); - - // fake a drag event fakeDragSequence(interaction, dragstartX, dragstartY, dragendX, dragendY); - assert.equal(timesCalled, 2, "drag callbacks area called twice"); }); - it("Highlights and un-highlights areas appropriately", function () { fakeDragSequence(interaction, dragstartX, dragstartY, dragendX, dragendY); var dragBoxClass = "." + Plottable.Interaction.XYDragBox.CLASS_DRAG_BOX; @@ -5706,64 +4642,46 @@ describe("Interactions", function () { assert.deepEqual(actualStartPosition, expectedStartPosition, "highlighted box is positioned correctly"); assert.equal(parseFloat(dragBox.attr("width")), svgWidth, "highlighted box has correct width"); assert.equal(parseFloat(dragBox.attr("height")), Math.abs(dragstartY - dragendY), "highlighted box has correct height"); - interaction.clearBox(); var boxGone = dragBox.attr("width") === "0" && dragBox.attr("height") === "0"; assert.isTrue(boxGone, "highlighted box disappears when clearBox is called"); }); - after(function () { svg.remove(); }); }); - describe("KeyInteraction", function () { it("Triggers the callback only when the Component is moused over and appropriate key is pressed", function () { var svg = generateSVG(400, 400); - - // svg.attr("id", "key-interaction-test"); var component = new Plottable.Abstract.Component(); component.renderTo(svg); - var code = 65; var ki = new Plottable.Interaction.Key(component, code); - var callbackCalled = false; var callback = function () { callbackCalled = true; }; - ki.callback(callback); ki.registerWithComponent(); - var $hitbox = $(component.hitBox.node()); - $hitbox.simulate("keydown", { keyCode: code }); assert.isFalse(callbackCalled, "callback is not called if component does not have mouse focus (before mouseover)"); - $hitbox.simulate("mouseover"); - $hitbox.simulate("keydown", { keyCode: code }); assert.isTrue(callbackCalled, "callback gets called if the appropriate key is pressed while the component has mouse focus"); - callbackCalled = false; $hitbox.simulate("keydown", { keyCode: (code + 1) }); assert.isFalse(callbackCalled, "callback is not called if the wrong key is pressed"); - $hitbox.simulate("mouseout"); - $hitbox.simulate("keydown", { keyCode: code }); assert.isFalse(callbackCalled, "callback is not called if component does not have mouse focus (after mouseout)"); - svg.remove(); }); }); - describe("BarHover", function () { var dataset; var ordinalScale; var linearScale; - before(function () { dataset = [ { name: "A", value: 3 }, @@ -5772,231 +4690,170 @@ describe("Interactions", function () { ordinalScale = new Plottable.Scale.Ordinal(); linearScale = new Plottable.Scale.Linear(); }); - it("hoverMode()", function () { var barPlot = new Plottable.Plot.VerticalBar(dataset, ordinalScale, linearScale); var bhi = new Plottable.Interaction.BarHover(barPlot); - bhi.hoverMode("line"); bhi.hoverMode("POINT"); - - assert.throws(function () { - return bhi.hoverMode("derp"); - }, "not a valid"); + assert.throws(function () { return bhi.hoverMode("derp"); }, "not a valid"); }); - it("correctly triggers callbacks (vertical)", function () { var svg = generateSVG(400, 400); var barPlot = new Plottable.Plot.VerticalBar(dataset, ordinalScale, linearScale); barPlot.project("x", "name", ordinalScale).project("y", "value", linearScale); var bhi = new Plottable.Interaction.BarHover(barPlot); - var barDatum = null; bhi.onHover(function (datum, bar) { barDatum = datum; }); - var unhoverCalled = false; bhi.onUnhover(function (datum, bar) { barDatum = datum; unhoverCalled = true; }); - barPlot.renderTo(svg); bhi.registerWithComponent(); - var hitbox = barPlot.element.select(".hit-box"); - triggerFakeMouseEvent("mousemove", hitbox, 100, 200); assert.deepEqual(barDatum, dataset[0], "the first bar was selected (point mode)"); barDatum = null; triggerFakeMouseEvent("mousemove", hitbox, 100, 201); assert.isNull(barDatum, "hover callback isn't called if the hovered bar didn't change"); - barDatum = null; triggerFakeMouseEvent("mousemove", hitbox, 10, 10); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing away from a bar"); assert.deepEqual(barDatum, dataset[0], "the unhover callback was passed the last-hovered bar"); - unhoverCalled = false; triggerFakeMouseEvent("mousemove", hitbox, 11, 11); assert.isFalse(unhoverCalled, "unhover callback isn't triggered multiple times in succession"); - triggerFakeMouseEvent("mousemove", hitbox, 100, 200); triggerFakeMouseEvent("mouseout", hitbox, 100, 9999); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing out of the chart"); - triggerFakeMouseEvent("mousemove", hitbox, 100, 200); unhoverCalled = false; triggerFakeMouseEvent("mousemove", hitbox, 250, 200); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing from one bar to another"); - bhi.hoverMode("line"); barDatum = null; triggerFakeMouseEvent("mousemove", hitbox, 100, 1); assert.deepEqual(barDatum, dataset[0], "the first bar was selected (line mode)"); - svg.remove(); }); - it("correctly triggers callbacks (hoizontal)", function () { var svg = generateSVG(400, 400); var barPlot = new Plottable.Plot.HorizontalBar(dataset, linearScale, ordinalScale); barPlot.project("y", "name", ordinalScale).project("x", "value", linearScale); var bhi = new Plottable.Interaction.BarHover(barPlot); - var barDatum = null; bhi.onHover(function (datum, bar) { barDatum = datum; }); - var unhoverCalled = false; bhi.onUnhover(function () { unhoverCalled = true; }); - barPlot.renderTo(svg); bhi.registerWithComponent(); - var hitbox = barPlot.element.select(".hit-box"); - triggerFakeMouseEvent("mousemove", hitbox, 200, 250); assert.deepEqual(barDatum, dataset[0], "the first bar was selected (point mode)"); barDatum = null; triggerFakeMouseEvent("mousemove", hitbox, 201, 250); assert.isNull(barDatum, "hover callback isn't called if the hovered bar didn't change"); - triggerFakeMouseEvent("mousemove", hitbox, 10, 10); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing away from a bar"); unhoverCalled = false; triggerFakeMouseEvent("mousemove", hitbox, 11, 11); assert.isFalse(unhoverCalled, "unhover callback isn't triggered multiple times in succession"); - triggerFakeMouseEvent("mousemove", hitbox, 200, 250); triggerFakeMouseEvent("mouseout", hitbox, -999, 250); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing out of the chart"); - triggerFakeMouseEvent("mousemove", hitbox, 200, 250); unhoverCalled = false; triggerFakeMouseEvent("mousemove", hitbox, 200, 100); assert.isTrue(unhoverCalled, "unhover callback is triggered on mousing from one bar to another"); - bhi.hoverMode("line"); triggerFakeMouseEvent("mousemove", hitbox, 399, 250); assert.deepEqual(barDatum, dataset[0], "the first bar was selected (line mode)"); - svg.remove(); }); }); }); -/// var assert = chai.assert; - describe("Dispatchers", function () { it("correctly registers for and deregisters from events", function () { var target = generateSVG(); - var dispatcher = new Plottable.Abstract.Dispatcher(target); var callbackWasCalled = false; dispatcher._event2Callback["click"] = function () { callbackWasCalled = true; }; - triggerFakeUIEvent("click", target); assert.isFalse(callbackWasCalled, "The callback is not called before the dispatcher connect()s"); - dispatcher.connect(); triggerFakeUIEvent("click", target); assert.isTrue(callbackWasCalled, "The dispatcher called its callback"); - callbackWasCalled = false; dispatcher.disconnect(); triggerFakeUIEvent("click", target); assert.isFalse(callbackWasCalled, "The callback is not called after the dispatcher disconnect()s"); - target.remove(); }); - it("target can be changed", function () { var target1 = generateSVG(); var target2 = generateSVG(); - var dispatcher = new Plottable.Abstract.Dispatcher(target1); var callbackWasCalled = false; - dispatcher._event2Callback["click"] = function () { - return callbackWasCalled = true; - }; - + dispatcher._event2Callback["click"] = function () { return callbackWasCalled = true; }; dispatcher.connect(); triggerFakeUIEvent("click", target1); assert.isTrue(callbackWasCalled, "The dispatcher received the event on the target"); - dispatcher.target(target2); callbackWasCalled = false; - triggerFakeUIEvent("click", target1); assert.isFalse(callbackWasCalled, "The dispatcher did not receive the event on the old target"); triggerFakeUIEvent("click", target2); assert.isTrue(callbackWasCalled, "The dispatcher received the event on the new target"); - target1.remove(); target2.remove(); }); - it("multiple dispatchers can be attached to the same target", function () { var target = generateSVG(); - var dispatcher1 = new Plottable.Abstract.Dispatcher(target); var called1 = false; - dispatcher1._event2Callback["click"] = function () { - return called1 = true; - }; + dispatcher1._event2Callback["click"] = function () { return called1 = true; }; dispatcher1.connect(); - var dispatcher2 = new Plottable.Abstract.Dispatcher(target); var called2 = false; - dispatcher2._event2Callback["click"] = function () { - return called2 = true; - }; + dispatcher2._event2Callback["click"] = function () { return called2 = true; }; dispatcher2.connect(); - triggerFakeUIEvent("click", target); assert.isTrue(called1, "The first dispatcher called its callback"); assert.isTrue(called2, "The second dispatcher also called its callback"); - target.remove(); }); - it("can't double-connect", function () { var target = generateSVG(); - var dispatcher = new Plottable.Abstract.Dispatcher(target); dispatcher.connect(); - assert.throws(function () { - return dispatcher.connect(); - }, "connect"); - + assert.throws(function () { return dispatcher.connect(); }, "connect"); target.remove(); }); - describe("Mouse Dispatcher", function () { it("passes event position to mouseover, mousemove, and mouseout callbacks", function () { var target = generateSVG(); - var targetX = 17; var targetY = 76; var expectedPoint = { x: targetX, y: targetY }; - function assertPointsClose(actual, expected, epsilon, message) { assert.closeTo(actual.x, expected.x, epsilon, message + " (x)"); assert.closeTo(actual.y, expected.y, epsilon, message + " (y)"); } ; - var md = new Plottable.Dispatcher.Mouse(target); var mouseoverCalled = false; md.mouseover(function (p) { @@ -6013,7 +4870,6 @@ describe("Dispatchers", function () { mouseoutCalled = true; assertPointsClose(p, expectedPoint, 0.5, "the mouse position was passed to the callback"); }); - md.connect(); triggerFakeMouseEvent("mouseover", target, targetX, targetY); assert.isTrue(mouseoverCalled, "mouseover callback was called"); @@ -6021,7 +4877,6 @@ describe("Dispatchers", function () { assert.isTrue(mousemoveCalled, "mousemove callback was called"); triggerFakeMouseEvent("mouseout", target, targetX, targetY); assert.isTrue(mouseoutCalled, "mouseout callback was called"); - target.remove(); }); });