Skip to content

Commit 79c3d59

Browse files
committed
rebase ; add picker on groups and bars
1 parent b6dc69a commit 79c3d59

File tree

7 files changed

+67
-37
lines changed

7 files changed

+67
-37
lines changed

src/mark.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ export class Mark {
4545
})
4646
};
4747
}
48+
update(g, values) {
49+
const svg = g.ownerSVGElement;
50+
console.log(values);
51+
svg.value = values;
52+
svg.dispatchEvent(new CustomEvent('input'));
53+
}
4854
}
4955

5056
// TODO Type coercion?

src/marks/bar.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class AbstractBar extends Mark {
4747
render(I, scales, channels, dimensions) {
4848
const {rx, ry} = this;
4949
const {color} = scales;
50-
const {z: Z, title: L, fill: F, stroke: S} = channels;
50+
const {z: Z, title: L, fill: F, stroke: S, picker: J} = channels;
5151
const index = filter(I, ...this._positions(channels), F, S);
5252
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
5353
return create("svg:g")
@@ -56,6 +56,10 @@ export class AbstractBar extends Mark {
5656
.call(g => g.selectAll()
5757
.data(index)
5858
.join("rect")
59+
.call(J ? rect => rect
60+
.on("click", (event, i) => super.update(event.currentTarget, J[i]))
61+
: () => {}
62+
)
5963
.call(applyDirectStyles, this)
6064
.attr("x", this._x(scales, channels, dimensions))
6165
.attr("width", this._width(scales, channels, dimensions))
@@ -89,13 +93,14 @@ export class AbstractBar extends Mark {
8993
}
9094

9195
export class BarX extends AbstractBar {
92-
constructor(data, {x1, x2, y, ...options} = {}) {
96+
constructor(data, {x1, x2, y, picker = d => d, ...options} = {}) {
9397
super(
9498
data,
9599
[
96100
{name: "x1", value: x1, scale: "x"},
97101
{name: "x2", value: x2, scale: "x"},
98-
{name: "y", value: y, scale: "y", type: "band", optional: true}
102+
{name: "y", value: y, scale: "y", type: "band", optional: true},
103+
{name: "picker", value: picker, optional: true}
99104
],
100105
options
101106
);
@@ -117,13 +122,14 @@ export class BarX extends AbstractBar {
117122
}
118123

119124
export class BarY extends AbstractBar {
120-
constructor(data, {x, y1, y2, ...options} = {}) {
125+
constructor(data, {x, y1, y2, picker = d => d, ...options} = {}) {
121126
super(
122127
data,
123128
[
124129
{name: "y1", value: y1, scale: "y"},
125130
{name: "y2", value: y2, scale: "y"},
126-
{name: "x", value: x, scale: "x", type: "band", optional: true}
131+
{name: "x", value: x, scale: "x", type: "band", optional: true},
132+
{name: "picker", value: picker, optional: true}
127133
],
128134
options
129135
);

src/marks/rect.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class Rect extends Mark {
1616
title,
1717
fill,
1818
stroke,
19+
picker = d => d,
1920
inset = 0,
2021
insetTop = inset,
2122
insetRight = inset,
@@ -38,7 +39,8 @@ export class Rect extends Mark {
3839
{name: "z", value: z, optional: true},
3940
{name: "title", value: title, optional: true},
4041
{name: "fill", value: vfill, scale: "color", optional: true},
41-
{name: "stroke", value: vstroke, scale: "color", optional: true}
42+
{name: "stroke", value: vstroke, scale: "color", optional: true},
43+
{name: "picker", value: picker, optional: true}
4244
],
4345
options
4446
);
@@ -53,7 +55,7 @@ export class Rect extends Mark {
5355
render(
5456
I,
5557
{x, y, color},
56-
{x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, fill: F, stroke: S}
58+
{x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, fill: F, stroke: S, picker: J}
5759
) {
5860
const {rx, ry} = this;
5961
const index = filter(I, X1, Y2, X2, Y2, F, S);
@@ -64,6 +66,10 @@ export class Rect extends Mark {
6466
.call(g => g.selectAll()
6567
.data(index)
6668
.join("rect")
69+
.call(J ? rect => rect
70+
.on("click", (event, i) => super.update(event.currentTarget, J[i]))
71+
: () => {}
72+
)
6773
.call(applyDirectStyles, this)
6874
.attr("x", i => Math.min(x(X1[i]), x(X2[i])) + this.insetLeft)
6975
.attr("y", i => Math.min(y(Y1[i]), y(Y2[i])) + this.insetTop)

src/transforms/bin.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ import {offset} from "../style.js";
66
// Group on y, z, fill, or stroke, if any, then bin on x.
77
export function binX({x, y, out = y == null ? "y" : "fill", inset, insetLeft, insetRight, ...options} = {}) {
88
([insetLeft, insetRight] = maybeInset(inset, insetLeft, insetRight));
9-
const [transform, x1, x2, l] = bin1(x, "y", {y, ...options});
10-
return {x1, x2, ...transform, inset, insetLeft, insetRight, [out]: l};
9+
const [transform, x1, x2, l, picker] = bin1(x, "y", {y, ...options});
10+
return {x1, x2, ...transform, picker, inset, insetLeft, insetRight, [out]: l};
1111
}
1212

1313
// Group on y, z, fill, or stroke, if any, then bin on x.
1414
export function binXMid({x, out = "r", ...options} = {}) {
15-
const [transform, x1, x2, l] = bin1(x, "y", options);
16-
return {x: mid(x1, x2), ...transform, [out]: l};
15+
const [transform, x1, x2, l, picker] = bin1(x, "y", options);
16+
return {x: mid(x1, x2), ...transform, picker, [out]: l};
1717
}
1818

1919
// Group on x, z, fill, or stroke, if any, then bin on y.
2020
export function binY({y, x, out = x == null ? "x" : "fill", inset, insetTop, insetBottom, ...options} = {}) {
2121
([insetTop, insetBottom] = maybeInset(inset, insetTop, insetBottom));
22-
const [transform, y1, y2, l] = bin1(y, "x", {x, ...options});
23-
return {y1, y2, ...transform, inset, insetTop, insetBottom, [out]: l};
22+
const [transform, y1, y2, l, picker] = bin1(y, "x", {x, ...options});
23+
return {y1, y2, ...transform, picker, inset, insetTop, insetBottom, [out]: l};
2424
}
2525

2626
// Group on y, z, fill, or stroke, if any, then bin on x.
2727
export function binYMid({y, out = "r", ...options} = {}) {
28-
const [transform, y1, y2, l] = bin1(y, "x", options);
29-
return {y: mid(y1, y2), ...transform, [out]: l};
28+
const [transform, y1, y2, l, picker] = bin1(y, "x", options);
29+
return {y: mid(y1, y2), ...transform, picker, [out]: l};
3030
}
3131

3232
// Group on z, fill, or stroke, if any, then bin on x and y.
@@ -39,8 +39,8 @@ export function binR({x, y, ...options} = {}) {
3939
export function bin({x, y, out = "fill", inset, insetTop, insetRight, insetBottom, insetLeft, ...options} = {}) {
4040
([insetTop, insetBottom] = maybeInset(inset, insetTop, insetBottom));
4141
([insetLeft, insetRight] = maybeInset(inset, insetLeft, insetRight));
42-
const [transform, x1, x2, y1, y2, l] = bin2(x, y, options);
43-
return {x1, x2, y1, y2, ...transform, inset, insetTop, insetRight, insetBottom, insetLeft, [out]: l};
42+
const [transform, x1, x2, y1, y2, l, picker] = bin2(x, y, options);
43+
return {x1, x2, y1, y2, ...transform, picker, inset, insetTop, insetRight, insetBottom, insetLeft, [out]: l};
4444
}
4545

4646
function bin1(x, key, {[key]: k, z, fill, stroke, weight, domain, thresholds, normalize, cumulative, ...options} = {}) {
@@ -55,6 +55,7 @@ function bin1(x, key, {[key]: k, z, fill, stroke, weight, domain, thresholds, no
5555
const [BZ, setBZ] = maybeLazyChannel(z);
5656
const [BF = fill, setBF] = maybeLazyChannel(vfill);
5757
const [BS = stroke, setBS] = maybeLazyChannel(vstroke);
58+
const [J, setJ] = lazyChannel();
5859
return [
5960
{
6061
...key && {[key]: BK},
@@ -107,12 +108,14 @@ function bin1(x, key, {[key]: k, z, fill, stroke, weight, domain, thresholds, no
107108
}
108109
binFacets.push(binFacet);
109110
}
111+
setJ(binData);
110112
return {data: binData, facets: binFacets};
111113
})
112114
},
113115
X1,
114116
X2,
115-
L
117+
L,
118+
J
116119
];
117120
}
118121

@@ -135,6 +138,7 @@ function bin2(x, y, {weight, domain, thresholds, normalize, z, fill, stroke, ...
135138
const [BZ, setBZ] = maybeLazyChannel(z);
136139
const [BF = fill, setBF] = maybeLazyChannel(vfill);
137140
const [BS = stroke, setBS] = maybeLazyChannel(vstroke);
141+
const [J, setJ] = lazyChannel();
138142
return [
139143
{
140144
z: BZ,
@@ -184,14 +188,16 @@ function bin2(x, y, {weight, domain, thresholds, normalize, z, fill, stroke, ...
184188
}
185189
binFacets.push(binFacet);
186190
}
191+
setJ(binData);
187192
return {data: binData, facets: binFacets};
188193
})
189194
},
190195
X1,
191196
X2,
192197
Y1,
193198
Y2,
194-
L
199+
L,
200+
J
195201
];
196202
}
197203

src/transforms/group.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import {valueof, maybeColor, maybeTransform, maybeValue, maybeLazyChannel, lazyC
44

55
// Group on y, z, fill, or stroke, if any, then group on x.
66
export function groupX({x, y, out = y == null ? "y" : "fill", ...options} = {}) {
7-
const [transform, X, l] = group1(x, "y", {y, ...options});
8-
return {x: X, ...transform, [out]: l};
7+
const [transform, X, l, picker] = group1(x, "y", {y, ...options});
8+
return {x: X, ...transform, picker, [out]: l};
99
}
1010

1111
// Group on x, z, fill, or stroke, if any, then group on y.
1212
export function groupY({y, x, out = x == null ? "x" : "fill", ...options} = {}) {
13-
const [transform, Y, l] = group1(y, "x", {x, ...options});
14-
return {y: Y, ...transform, [out]: l};
13+
const [transform, Y, l, picker] = group1(y, "x", {x, ...options});
14+
return {y: Y, ...transform, picker, [out]: l};
1515
}
1616

1717
// Group on z, fill, or stroke, if any.
@@ -20,8 +20,8 @@ export function groupR(options) {
2020
}
2121

2222
export function group({x, y, out = "fill", ...options} = {}) {
23-
const [transform, X, Y, L] = group2(x, y, options);
24-
return {x: X, y: Y, ...transform, [out]: L};
23+
const [transform, X, Y, L, picker] = group2(x, y, options);
24+
return {x: X, y: Y, ...transform, picker, [out]: L};
2525
}
2626

2727
function group1(x = identity, key, {[key]: k, weight, domain, normalize, z, fill, stroke, ...options} = {}) {
@@ -34,6 +34,7 @@ function group1(x = identity, key, {[key]: k, weight, domain, normalize, z, fill
3434
const [BZ, setBZ] = maybeLazyChannel(z);
3535
const [BF = fill, setBF] = maybeLazyChannel(vfill);
3636
const [BS = stroke, setBS] = maybeLazyChannel(vstroke);
37+
const [J, setJ] = lazyChannel();
3738
const defined = maybeDomain(domain);
3839
return [
3940
{
@@ -79,11 +80,13 @@ function group1(x = identity, key, {[key]: k, weight, domain, normalize, z, fill
7980
}
8081
groupFacets.push(groupFacet);
8182
}
83+
setJ(groupData);
8284
return {data: groupData, facets: groupFacets};
8385
})
8486
},
8587
X,
86-
L
88+
L,
89+
J
8790
];
8891
}
8992

@@ -100,6 +103,7 @@ function group2(xv, yv, {z, fill, stroke, weight, domain, normalize, ...options}
100103
const [vstroke] = maybeColor(stroke);
101104
const [F = fill, setF] = maybeLazyChannel(vfill);
102105
const [S = stroke, setS] = maybeLazyChannel(vstroke);
106+
const [J, setJ] = lazyChannel();
103107
const xdefined = maybeDomain(xdomain);
104108
const ydefined = maybeDomain(ydomain);
105109
return [
@@ -148,12 +152,14 @@ function group2(xv, yv, {z, fill, stroke, weight, domain, normalize, ...options}
148152
}
149153
groupFacets.push(groupFacet);
150154
}
155+
setJ(groupData);
151156
return {data: groupData, facets: groupFacets};
152157
})
153158
},
154159
X,
155160
Y,
156-
L
161+
L,
162+
J
157163
];
158164
}
159165

test/marks/bar-test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ tape("barX() has the expected defaults", test => {
55
const bar = Plot.barX();
66
test.strictEqual(bar.data, undefined);
77
test.strictEqual(bar.transform, undefined);
8-
test.deepEqual(bar.channels.map(c => c.name), ["x1", "x2"]);
9-
test.deepEqual(bar.channels.map(c => Plot.valueof([1, 2, 3], c.value)), [[0, 0, 0], [1, 2, 3]]);
10-
test.deepEqual(bar.channels.map(c => c.scale), ["x", "x"]);
8+
test.deepEqual(bar.channels.map(c => c.name), ["x1", "x2", "picker"]);
9+
test.deepEqual(bar.channels.map(c => Plot.valueof([1, 2, 3], c.value)), [[0, 0, 0], [1, 2, 3], [1, 2, 3]]);
10+
test.deepEqual(bar.channels.map(c => c.scale), ["x", "x", undefined]);
1111
test.strictEqual(bar.fill, undefined);
1212
test.strictEqual(bar.fillOpacity, undefined);
1313
test.strictEqual(bar.stroke, undefined);
@@ -26,8 +26,8 @@ tape("barX() has the expected defaults", test => {
2626

2727
tape("barX(data, {y}) uses a band scale", test => {
2828
const bar = Plot.barX(undefined, {y: "x"});
29-
test.deepEqual(bar.channels.map(c => c.name), ["x1", "x2", "y"]);
30-
test.deepEqual(bar.channels.map(c => c.scale), ["x", "x", "y"]);
29+
test.deepEqual(bar.channels.map(c => c.name), ["x1", "x2", "y", "picker"]);
30+
test.deepEqual(bar.channels.map(c => c.scale), ["x", "x", "y", undefined]);
3131
test.strictEqual(bar.channels.find(c => c.name === "y").type, "band");
3232
test.strictEqual(bar.channels.find(c => c.name === "y").value.label, "x");
3333
});
@@ -99,9 +99,9 @@ tape("barY() has the expected defaults", test => {
9999
const bar = Plot.barY();
100100
test.strictEqual(bar.data, undefined);
101101
test.strictEqual(bar.transform, undefined);
102-
test.deepEqual(bar.channels.map(c => c.name), ["y1", "y2"]);
103-
test.deepEqual(bar.channels.map(c => Plot.valueof([1, 2, 3], c.value)), [[0, 0, 0], [1, 2, 3]]);
104-
test.deepEqual(bar.channels.map(c => c.scale), ["y", "y"]);
102+
test.deepEqual(bar.channels.map(c => c.name), ["y1", "y2", "picker"]);
103+
test.deepEqual(bar.channels.map(c => Plot.valueof([1, 2, 3], c.value)), [[0, 0, 0], [1, 2, 3], [1, 2, 3]]);
104+
test.deepEqual(bar.channels.map(c => c.scale), ["y", "y", undefined]);
105105
test.strictEqual(bar.fill, undefined);
106106
test.strictEqual(bar.fillOpacity, undefined);
107107
test.strictEqual(bar.stroke, undefined);
@@ -119,7 +119,7 @@ tape("barY() has the expected defaults", test => {
119119
});
120120

121121
tape("barY(data, {x}) uses a band scale", test => {
122-
const bar = Plot.barY(undefined, {x: "y"});
122+
const bar = Plot.barY(undefined, {x: "y", picker: null});
123123
test.deepEqual(bar.channels.map(c => c.name), ["y1", "y2", "x"]);
124124
test.deepEqual(bar.channels.map(c => c.scale), ["y", "y", "x"]);
125125
test.strictEqual(bar.channels.find(c => c.name === "x").type, "band");

test/marks/rect-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as Plot from "@observablehq/plot";
22
import tape from "tape-await";
33

44
tape("rect(data, options) has the expected defaults", test => {
5-
const rect = Plot.rect(undefined, {x1: "0", y1: "1", x2: "2", y2: "3"});
5+
const rect = Plot.rect(undefined, {x1: "0", y1: "1", x2: "2", y2: "3", picker: null});
66
test.strictEqual(rect.data, undefined);
77
test.strictEqual(rect.transform, undefined);
88
test.deepEqual(rect.channels.map(c => c.name), ["x1", "y1", "x2", "y2"]);

0 commit comments

Comments
 (0)