From 7e822192e5e8e91c4602815ab23f1af63c0aaa9f Mon Sep 17 00:00:00 2001 From: Matthias Jobst Date: Tue, 28 Nov 2017 12:05:04 +0100 Subject: [PATCH 1/4] D3 V3: Update to insert and force charts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added optionality to parameter in insert Added number as initial value in Link Added Date as allowed return für brushing on Date charts Extended Primitive --- types/d3/v3/index.d.ts | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/types/d3/v3/index.d.ts b/types/d3/v3/index.d.ts index 0fbc7502b0..fabb96be43 100644 --- a/types/d3/v3/index.d.ts +++ b/types/d3/v3/index.d.ts @@ -1,6 +1,8 @@ // Type definitions for d3JS 3.5 // Project: http://d3js.org/ -// Definitions by: Alex Ford , Boris Yankov +// Definitions by: Alex Ford +// Boris Yankov +// Matthias Jobst // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // Latest patch version of module validated against: 3.5.17 @@ -233,28 +235,30 @@ declare namespace d3 { * @param name the element name to append. May be prefixed (see d3.ns.prefix). * @param before the selector to determine position (e.g., ":first-child") */ - insert(name: string, before: string): Update; + // https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#insert + insert(name: string, before?: string): Update; /** * Inserts a new child to each node in the selection. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the element name to append. May be prefixed (see d3.ns.prefix). * @param before a function to determine the node to use as the next sibling */ - insert(name: string, before: (datum: Datum, index: number, outerIndex: number) => EventTarget): Update; + // https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#insert + insert(name: string, before?: (datum: Datum, index: number, outerIndex: number) => EventTarget): Update; /** * Inserts a new child to the end of each node in the selection by computing a new node. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the function to compute a new child * @param before the selector to determine position (e.g., ":first-child") */ - insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before: string): Update; + insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before?: string): Update; /** * Inserts a new child to the end of each node in the selection by computing a new node. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the function to compute a new child * @param before a function to determine the node to use as the next sibling */ - insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before: (datum: Datum, index: number, outerIndex: number) => EventTarget): Update; + insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before?: (datum: Datum, index: number, outerIndex: number) => EventTarget): Update; /** * Removes the elements from the DOM. They are in a detached state and may be re-added (though there is currently no dedicated API for doing so). @@ -429,7 +433,7 @@ declare namespace d3 { /** * Administrivia: JavaScript primitive types, or "things that toString() predictably". */ - export type Primitive = number | string | boolean; + export type Primitive = number | string | boolean | Date | undefined; /** * Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations @@ -626,28 +630,28 @@ declare namespace d3 { * @param name the element name to append. May be prefixed (see d3.ns.prefix). * @param before the selector to determine position (e.g., ":first-child") */ - insert(name: string, before: string): Selection; + insert(name: string, before?: string): Selection; /** * Inserts a new child to each node in the selection. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the element name to append. May be prefixed (see d3.ns.prefix). * @param before a function to determine the node to use as the next sibling */ - insert(name: string, before: (datum: Datum, index: number, outerIndex: number) => EventTarget): Selection; + insert(name: string, before?: (datum: Datum, index: number, outerIndex: number) => EventTarget): Selection; /** * Inserts a new child to the end of each node in the selection by computing a new node. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the function to compute a new child * @param before the selector to determine position (e.g., ":first-child") */ - insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before: string): Selection; + insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before?: string): Selection; /** * Inserts a new child to the end of each node in the selection by computing a new node. This child will inherit its parent's data (if available). Returns a fresh selection consisting of the newly-inserted children. * @param name the function to compute a new child * @param before a function to determine the node to use as the next sibling */ - insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before: (datum: Datum, index: number, outerIndex: number) => EventTarget): Selection; + insert(name: (datum: Datum, index: number, outerIndex: number) => EventTarget, before?: (datum: Datum, index: number, outerIndex: number) => EventTarget): Selection; /** * Removes the elements from the DOM. They are in a detached state and may be re-added (though there is currently no dedicated API for doing so). @@ -2605,7 +2609,8 @@ declare namespace d3 { y(): brush.Scale; y(y: brush.Scale): Brush; - extent(): [number, number] | [[number, number], [number, number]]; + // https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Controls.md#brush_extent + extent(): [number, number] | [[number, number], [number, number]] | [Date, Date]; extent(extent: [number, number] | [[number, number], [number, number]]): Brush; clamp(): boolean | [boolean, boolean]; @@ -2874,10 +2879,12 @@ declare namespace d3 { export function force(): Force, Node>; export function force, Node extends force.Node>(): Force; + // https://github.com/d3/d3-3.x-api-reference/blob/master/Force-Layout.md#links + // Read the note at the end of the section where it talks about initial numbering namespace force { interface Link { - source: T; - target: T; + source: T|number; + target: T|number; } interface Node { From c86c33b89cd2d218d3ac55ce60d2b539403b01fe Mon Sep 17 00:00:00 2001 From: Matthias Jobst Date: Tue, 28 Nov 2017 12:08:07 +0100 Subject: [PATCH 2/4] Modified tests to fit with new definitions --- types/d3/v3/d3-tests.ts | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/types/d3/v3/d3-tests.ts b/types/d3/v3/d3-tests.ts index 87b57e8261..4f50ef0341 100644 --- a/types/d3/v3/d3-tests.ts +++ b/types/d3/v3/d3-tests.ts @@ -1051,7 +1051,7 @@ namespace forceCollapsable { var force = d3.layout.force() .on("tick", tick) .charge(function (d) { return d._children ? -d.size / 100 : -30; } ) - .linkDistance(function (d) { return d.target._children ? 80 : 30; } ) + .linkDistance(function (d) { return (d.target as Node)._children ? 80 : 30; } ) .size([w, h - 160]); var vis = d3.select("body").append("svg:svg") @@ -1083,10 +1083,10 @@ namespace forceCollapsable { // Enter any new links. link.enter().insert("svg:line", ".node") .attr("class", "link") - .attr("x1", function (d) { return d.source.x; } ) - .attr("y1", function (d) { return d.source.y; } ) - .attr("x2", function (d) { return d.target.x; } ) - .attr("y2", function (d) { return d.target.y; } ); + .attr("x1", function (d) { return (d.source as Node).x; } ) + .attr("y1", function (d) { return (d.source as Node).y; } ) + .attr("x2", function (d) { return (d.target as Node).x; } ) + .attr("y2", function (d) { return (d.target as Node).y; } ); // Exit any old links. link.exit().remove(); @@ -1114,10 +1114,10 @@ namespace forceCollapsable { } function tick() { - link.attr("x1", function (d) { return d.source.x; } ) - .attr("y1", function (d) { return d.source.y; } ) - .attr("x2", function (d) { return d.target.x; } ) - .attr("y2", function (d) { return d.target.y; } ); + link.attr("x1", function (d) { return (d.source as Node).x; } ) + .attr("y1", function (d) { return (d.source as Node).y; } ) + .attr("x2", function (d) { return (d.target as Node).x; } ) + .attr("y2", function (d) { return (d.target as Node).y; } ); node.attr("cx", function (d) { return d.x; } ) .attr("cy", function (d) { return d.y; } ); @@ -1738,7 +1738,7 @@ namespace forceCollapsable2 { var force = d3.layout.force() .on("tick", tick) .charge(function (d) { return d._children ? -d.size / 100 : -30; } ) - .linkDistance(function (d) { return d.target._children ? 80 : 30; } ) + .linkDistance(function (d) { return (d.target as Node)._children ? 80 : 30; } ) .size([w, h - 160]); var vis = d3.select("body").append("svg:svg") @@ -1770,10 +1770,10 @@ namespace forceCollapsable2 { // Enter any new links. link.enter().insert("svg:line", ".node") .attr("class", "link") - .attr("x1", function (d) { return d.source.x; } ) - .attr("y1", function (d) { return d.source.y; } ) - .attr("x2", function (d) { return d.target.x; } ) - .attr("y2", function (d) { return d.target.y; } ); + .attr("x1", function (d) { return (d.source as Node).x; } ) + .attr("y1", function (d) { return (d.source as Node).y; } ) + .attr("x2", function (d) { return (d.target as Node).x; } ) + .attr("y2", function (d) { return (d.target as Node).y; } ); // Exit any old links. link.exit().remove(); @@ -1801,11 +1801,11 @@ namespace forceCollapsable2 { } function tick() { - link.attr("x1", function (d) { return d.source.x; } ) - .attr("y1", function (d) { return d.source.y; } ) - .attr("x2", function (d) { return d.target.x; } ) - .attr("y2", function (d) { return d.target.y; } ); - + link.attr("x1", function (d) { return (d.source as Node).x; } ) + .attr("y1", function (d) { return (d.source as Node).y; } ) + .attr("x2", function (d) { return (d.target as Node).x; } ) + .attr("y2", function (d) { return (d.target as Node).y; } ); + node.attr("cx", function (d) { return d.x; } ) .attr("cy", function (d) { return d.y; } ); } From 61ff9913e1b97c1d7e4cba7cd0be8dee42c798b5 Mon Sep 17 00:00:00 2001 From: Matthias Jobst Date: Thu, 30 Nov 2017 11:54:46 +0100 Subject: [PATCH 3/4] Added Date to brush.Scale and removed it from Primitive --- types/d3/v3/index.d.ts | 88 +++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/types/d3/v3/index.d.ts b/types/d3/v3/index.d.ts index fabb96be43..2642ecd5d3 100644 --- a/types/d3/v3/index.d.ts +++ b/types/d3/v3/index.d.ts @@ -433,7 +433,7 @@ declare namespace d3 { /** * Administrivia: JavaScript primitive types, or "things that toString() predictably". */ - export type Primitive = number | string | boolean | Date | undefined; + export type Primitive = number | string | boolean ; /** * Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations @@ -932,28 +932,28 @@ declare namespace d3 { export function flush(): void; } - interface BaseEvent { - type: string; - sourceEvent?: Event; - } + interface BaseEvent { + type: string; + sourceEvent?: Event; + } - /** - * Define a D3-specific ZoomEvent per https://github.com/mbostock/d3/wiki/Zoom-Behavior#event - */ - interface ZoomEvent extends BaseEvent { - scale: number; - translate: [number, number]; - } + /** + * Define a D3-specific ZoomEvent per https://github.com/mbostock/d3/wiki/Zoom-Behavior#event + */ + interface ZoomEvent extends BaseEvent { + scale: number; + translate: [number, number]; + } - /** - * Define a D3-specific DragEvent per https://github.com/mbostock/d3/wiki/Drag-Behavior#on - */ - interface DragEvent extends BaseEvent { - x: number; - y: number; - dx: number; - dy: number; - } + /** + * Define a D3-specific DragEvent per https://github.com/mbostock/d3/wiki/Drag-Behavior#on + */ + interface DragEvent extends BaseEvent { + x: number; + y: number; + dx: number; + dy: number; + } /** * The current event's value. Use this variable in a handler registered with `selection.on`. @@ -1391,8 +1391,8 @@ declare namespace d3 { export function requote(string: string): string; export var rgb: { - new (r: number, g: number, b: number): Rgb; - new (color: string): Rgb; + new(r: number, g: number, b: number): Rgb; + new(color: string): Rgb; (r: number, g: number, b: number): Rgb; (color: string): Rgb; @@ -1412,8 +1412,8 @@ declare namespace d3 { } export var hsl: { - new (h: number, s: number, l: number): Hsl; - new (color: string): Hsl; + new(h: number, s: number, l: number): Hsl; + new(color: string): Hsl; (h: number, s: number, l: number): Hsl; (color: string): Hsl; @@ -1433,8 +1433,8 @@ declare namespace d3 { } export var hcl: { - new (h: number, c: number, l: number): Hcl; - new (color: string): Hcl; + new(h: number, c: number, l: number): Hcl; + new(color: string): Hcl; (h: number, c: number, l: number): Hcl; (color: string): Hcl; @@ -1450,8 +1450,8 @@ declare namespace d3 { } export var lab: { - new (l: number, a: number, b: number): Lab; - new (color: string): Lab; + new(l: number, a: number, b: number): Lab; + new(color: string): Lab; (l: number, a: number, b: number): Lab; (color: string): Lab; @@ -1471,7 +1471,7 @@ declare namespace d3 { export var color: { (): Color; - new (): Color; + new(): Color; }; interface Color { @@ -1685,7 +1685,7 @@ declare namespace d3 { export function category20(): Ordinal; export function category20b(): Ordinal; export function category20b(): Ordinal; - export function category20c(): Ordinal; + export function category20c(): Ordinal; export function category20c(): Ordinal; interface Ordinal { @@ -1822,10 +1822,10 @@ declare namespace d3 { export function format(specifier: string): Format; export module format { - export function multi(formats: Array<[string, (d: Date) => boolean|number]>): Format; + export function multi(formats: Array<[string, (d: Date) => boolean | number]>): Format; export function utc(specifier: string): Format; namespace utc { - export function multi(formats: Array<[string, (d: Date) => boolean|number]>): Format; + export function multi(formats: Array<[string, (d: Date) => boolean | number]>): Format; } export var iso: Format; @@ -2578,7 +2578,7 @@ declare namespace d3 { tickFormat(): (t: any) => string; tickFormat(format: (t: any) => string): Axis; - tickFormat(format:string): Axis; + tickFormat(format: string): Axis; } export function brush(): Brush; @@ -2586,13 +2586,13 @@ declare namespace d3 { namespace brush { interface Scale { - domain(): number[]; - domain(domain: number[]): Scale; + domain(): number[] | Date[]; + domain(domain: number[] | Date[]): Scale; - range(): number[]; - range(range: number[]): Scale; + range(): number[] | Date[]; + range(range: number[] | Date[]): Scale; - invert?(y: number): number; + invert?(y: number | Date): number | Date; } } @@ -2610,8 +2610,8 @@ declare namespace d3 { y(y: brush.Scale): Brush; // https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Controls.md#brush_extent - extent(): [number, number] | [[number, number], [number, number]] | [Date, Date]; - extent(extent: [number, number] | [[number, number], [number, number]]): Brush; + extent(): [number, number] | [[number, number], [number, number]] | [Date, Date] | [[Date, Date],[Date,Date]]; + extent(extent: [number, number] | [[number, number], [number, number]] | [Date, Date] | [[Date, Date], [Date, Date]]): Brush; clamp(): boolean | [boolean, boolean]; clamp(clamp: boolean | [boolean, boolean]): Brush; @@ -2764,7 +2764,7 @@ declare namespace d3 { timeFormat: { (specifier: string): time.Format; utc(specifier: string): time.Format; - multi(formats: Array<[string, (d: Date) => boolean|number]>): time.Format; + multi(formats: Array<[string, (d: Date) => boolean | number]>): time.Format; } } @@ -2883,8 +2883,8 @@ declare namespace d3 { // Read the note at the end of the section where it talks about initial numbering namespace force { interface Link { - source: T|number; - target: T|number; + source: T | number; + target: T | number; } interface Node { From 7be1d3666ccc8cdab59771344ccb0eb102f71c53 Mon Sep 17 00:00:00 2001 From: Matthias Jobst Date: Fri, 1 Dec 2017 13:17:06 +0100 Subject: [PATCH 4/4] Added tests for brush on different axis classes This required some refactoring of the original brush code. Scale contains a generic. Brush can take up to three generics. --- types/d3/v3/d3-tests.ts | 31 +++++++++++++++++++++++++++++ types/d3/v3/index.d.ts | 44 ++++++++++++++++++++++------------------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/types/d3/v3/d3-tests.ts b/types/d3/v3/d3-tests.ts index 4f50ef0341..8704448c9b 100644 --- a/types/d3/v3/d3-tests.ts +++ b/types/d3/v3/d3-tests.ts @@ -2720,3 +2720,34 @@ function testEnterSizeEmpty() { selectionSize = newNodes.size(); } + +// Example from Matthias Jobst http://github.com/MatthiasJobst +// Checks the brush with different Axis types +class BrushAxisTest { + brush: d3.svg.Brush; + constructor() { + let scale = d3.time.scale(); + this.brush = d3.svg.brush() + .x(scale) // the x accessor accepts time scales + .y(scale); // as does y + } + brushes = () => { + let extent = this.brush.extent(); + let brush = d3.svg.brush(); + brush.x(d3.scale.linear()); // Linear scale + brush.y(d3.scale.log()); // Logarithmic scale + // Does not work: + // brush.extent(this.brush.extent()); + // From https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#ordinal_rangePoints + let ordinalScale = d3.scale.ordinal() + .domain([1, 2, 3, 4]) + .rangePoints([0, 100]); + let ordinalBrush = d3.svg.brush() + .x(ordinalScale) // Ordinal scale + .y(d3.scale.linear()); + let colorScale = d3.scale.category10(); + let colorBrush = d3.svg.brush() + .x(colorScale) // Color scale + .y(d3.scale.pow()); + } +} \ No newline at end of file diff --git a/types/d3/v3/index.d.ts b/types/d3/v3/index.d.ts index 2642ecd5d3..9a2f9ae34a 100644 --- a/types/d3/v3/index.d.ts +++ b/types/d3/v3/index.d.ts @@ -2581,40 +2581,44 @@ declare namespace d3 { tickFormat(format: string): Axis; } - export function brush(): Brush; - export function brush(): Brush; + export function brush(): Brush; + export function brush(): Brush; + export function brush(): Brush; + export function brush(): Brush; namespace brush { - interface Scale { - domain(): number[] | Date[]; - domain(domain: number[] | Date[]): Scale; + interface Scale { + domain(): S[]; + domain(domain: S[]): Scale; - range(): number[] | Date[]; - range(range: number[] | Date[]): Scale; + range(): S[]; + range(range: number[]): Scale; - invert?(y: number | Date): number | Date; + invert?(y: number): S; } } - interface Brush { + interface Brush { (selection: Selection): void; (selection: Transition): void; event(selection: Selection): void; event(selection: Transition): void; - x(): brush.Scale; - x(x: brush.Scale): Brush; + x(): brush.Scale; + x(x: brush.Scale): Brush; + x(x: d3.scale.Ordinal | d3.time.Scale): Brush; - y(): brush.Scale; - y(y: brush.Scale): Brush; + y(): brush.Scale; + y(y: brush.Scale): Brush; + y(x: d3.scale.Ordinal | d3.time.Scale): Brush; // https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Controls.md#brush_extent - extent(): [number, number] | [[number, number], [number, number]] | [Date, Date] | [[Date, Date],[Date,Date]]; - extent(extent: [number, number] | [[number, number], [number, number]] | [Date, Date] | [[Date, Date], [Date, Date]]): Brush; + extent(): [X, X] | [Y, Y] | [[X, Y], [X, Y]] | null; + extent(extent: [X, X] | [Y, Y] | [[X, Y], [X, Y]]): Brush; clamp(): boolean | [boolean, boolean]; - clamp(clamp: boolean | [boolean, boolean]): Brush; + clamp(clamp: boolean | [boolean, boolean]): Brush; clear(): void; @@ -2625,10 +2629,10 @@ declare namespace d3 { on(type: 'brushend'): (datum: T, index: number) => void; on(type: string): (datum: T, index: number) => void; - on(type: 'brushstart', listener: (datum: T, index: number) => void): Brush; - on(type: 'brush', listener: (datum: T, index: number) => void): Brush; - on(type: 'brushend', listener: (datum: T, index: number) => void): Brush; - on(type: string, listener: (datum: T, index: number) => void): Brush; + on(type: 'brushstart', listener: (datum: T, index: number) => void): Brush; + on(type: 'brush', listener: (datum: T, index: number) => void): Brush; + on(type: 'brushend', listener: (datum: T, index: number) => void): Brush; + on(type: string, listener: (datum: T, index: number) => void): Brush; } }