@jrkasprzyk/parcoord-es 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/parcoords.esm.js +26 -15
- package/dist/parcoords.esm.js.map +1 -1
- package/dist/parcoords.js +26 -15
- package/dist/parcoords.js.map +1 -1
- package/package.json +1 -1
- package/src/api/brushable.js +86 -81
- package/src/brush/1d/brushFor.js +94 -92
- package/src/brush/1d-multi/newBrush.js +104 -102
package/package.json
CHANGED
package/src/api/brushable.js
CHANGED
|
@@ -1,81 +1,86 @@
|
|
|
1
|
-
import { brushSelection, brushY } from 'd3-brush';
|
|
2
|
-
import { select } from 'd3-selection';
|
|
3
|
-
|
|
4
|
-
const brushable = (config, pc, flags) =>
|
|
5
|
-
function() {
|
|
6
|
-
if (!pc.g()) {
|
|
7
|
-
pc.createAxes();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const g = pc.g();
|
|
11
|
-
|
|
12
|
-
// Add and store a brush for each axis.
|
|
13
|
-
g.append('svg:g')
|
|
14
|
-
.attr('class', 'brush')
|
|
15
|
-
.each(function(d) {
|
|
16
|
-
if (config.dimensions[d] !== undefined) {
|
|
17
|
-
config.dimensions[d]['brush'] = brushY(select(this)).extent([
|
|
18
|
-
[-15, 0],
|
|
19
|
-
[15, config.dimensions[d].yscale.range()[0]],
|
|
20
|
-
]);
|
|
21
|
-
select(this).call(
|
|
22
|
-
config.dimensions[d]['brush']
|
|
23
|
-
.on('start', function(event) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
config.
|
|
62
|
-
select(this)
|
|
63
|
-
.select('.
|
|
64
|
-
.
|
|
65
|
-
pc.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
import { brushSelection, brushY } from 'd3-brush';
|
|
2
|
+
import { select } from 'd3-selection';
|
|
3
|
+
|
|
4
|
+
const brushable = (config, pc, flags) =>
|
|
5
|
+
function() {
|
|
6
|
+
if (!pc.g()) {
|
|
7
|
+
pc.createAxes();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const g = pc.g();
|
|
11
|
+
|
|
12
|
+
// Add and store a brush for each axis.
|
|
13
|
+
g.append('svg:g')
|
|
14
|
+
.attr('class', 'brush')
|
|
15
|
+
.each(function(d) {
|
|
16
|
+
if (config.dimensions[d] !== undefined) {
|
|
17
|
+
config.dimensions[d]['brush'] = brushY(select(this)).extent([
|
|
18
|
+
[-15, 0],
|
|
19
|
+
[15, config.dimensions[d].yscale.range()[0]],
|
|
20
|
+
]);
|
|
21
|
+
select(this).call(
|
|
22
|
+
config.dimensions[d]['brush']
|
|
23
|
+
.on('start', function(event) {
|
|
24
|
+
// `!=` also catches the undefined d3 v6+ uses for a
|
|
25
|
+
// programmatic brush.move, which `!== null` let through
|
|
26
|
+
// straight into the .ctrlKey dereference below.
|
|
27
|
+
if (event.sourceEvent != null && !event.sourceEvent.ctrlKey) {
|
|
28
|
+
pc.brushReset();
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
.on('brush', function(event) {
|
|
32
|
+
// A programmatic brush.move leaves sourceEvent undefined in
|
|
33
|
+
// d3 v6+; treat that as "no Ctrl key" rather than dereferencing.
|
|
34
|
+
if (!(event.sourceEvent && event.sourceEvent.ctrlKey)) {
|
|
35
|
+
pc.brush();
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.on('end', function(event) {
|
|
39
|
+
// save brush selection is ctrl key is held
|
|
40
|
+
// store important brush information and
|
|
41
|
+
// the html element of the selection,
|
|
42
|
+
// to make a dummy selection element
|
|
43
|
+
if (event.sourceEvent && event.sourceEvent.ctrlKey) {
|
|
44
|
+
let html = select(this)
|
|
45
|
+
.select('.selection')
|
|
46
|
+
.nodes()[0].outerHTML;
|
|
47
|
+
html = html.replace(
|
|
48
|
+
'class="selection"',
|
|
49
|
+
'class="selection dummy' +
|
|
50
|
+
' selection-' +
|
|
51
|
+
config.brushes.length +
|
|
52
|
+
'"'
|
|
53
|
+
);
|
|
54
|
+
let dat = select(this).nodes()[0].__data__;
|
|
55
|
+
let brush = {
|
|
56
|
+
id: config.brushes.length,
|
|
57
|
+
extent: brushSelection(this),
|
|
58
|
+
html: html,
|
|
59
|
+
data: dat,
|
|
60
|
+
};
|
|
61
|
+
config.brushes.push(brush);
|
|
62
|
+
select(select(this).nodes()[0].parentNode)
|
|
63
|
+
.select('.axis')
|
|
64
|
+
.nodes()[0].outerHTML += html;
|
|
65
|
+
pc.brush();
|
|
66
|
+
config.dimensions[d].brush.move(select(this, null));
|
|
67
|
+
select(this)
|
|
68
|
+
.select('.selection')
|
|
69
|
+
.attr('style', 'display:none');
|
|
70
|
+
pc.brushable();
|
|
71
|
+
} else {
|
|
72
|
+
pc.brush();
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
select(this).on('dblclick', function() {
|
|
77
|
+
pc.brushReset(d);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
flags.brushable = true;
|
|
83
|
+
return this;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default brushable;
|
package/src/brush/1d/brushFor.js
CHANGED
|
@@ -1,92 +1,94 @@
|
|
|
1
|
-
import { brushY, brushSelection } from 'd3-brush';
|
|
2
|
-
import invertByScale from '../invertByScale';
|
|
3
|
-
import selected from './selected';
|
|
4
|
-
|
|
5
|
-
const brushUpdated = (config, pc, events, args) => newSelection => {
|
|
6
|
-
config.brushed = newSelection;
|
|
7
|
-
events.call('brush', pc, config.brushed, args);
|
|
8
|
-
pc.renderBrushed();
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const brushFor = (state, config, pc, events, brushGroup) => (
|
|
12
|
-
axis,
|
|
13
|
-
_selector
|
|
14
|
-
) => {
|
|
15
|
-
// handle hidden axes which will not be a property of dimensions
|
|
16
|
-
if (!config.dimensions.hasOwnProperty(axis)) {
|
|
17
|
-
return () => {};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const brushRangeMax =
|
|
21
|
-
config.dimensions[axis].type === 'string'
|
|
22
|
-
? config.dimensions[axis].yscale.range()[
|
|
23
|
-
config.dimensions[axis].yscale.range().length - 1
|
|
24
|
-
]
|
|
25
|
-
: config.dimensions[axis].yscale.range()[0];
|
|
26
|
-
|
|
27
|
-
const _brush = brushY(_selector).extent([[-15, 0], [15, brushRangeMax]]);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const raw = brushSelection(
|
|
34
|
-
|
|
35
|
-
// handle hidden axes which will not have a yscale
|
|
36
|
-
let yscale = null;
|
|
37
|
-
if (config.dimensions.hasOwnProperty(axis)) {
|
|
38
|
-
yscale = config.dimensions[axis].yscale;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ordinal scales do not have invert
|
|
42
|
-
const scaled = invertByScale(raw, yscale);
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
axis
|
|
46
|
-
node
|
|
47
|
-
selection: {
|
|
48
|
-
raw,
|
|
49
|
-
scaled,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
_brush
|
|
55
|
-
.on('start', function(event) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
1
|
+
import { brushY, brushSelection } from 'd3-brush';
|
|
2
|
+
import invertByScale from '../invertByScale';
|
|
3
|
+
import selected from './selected';
|
|
4
|
+
|
|
5
|
+
const brushUpdated = (config, pc, events, args) => newSelection => {
|
|
6
|
+
config.brushed = newSelection;
|
|
7
|
+
events.call('brush', pc, config.brushed, args);
|
|
8
|
+
pc.renderBrushed();
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const brushFor = (state, config, pc, events, brushGroup) => (
|
|
12
|
+
axis,
|
|
13
|
+
_selector
|
|
14
|
+
) => {
|
|
15
|
+
// handle hidden axes which will not be a property of dimensions
|
|
16
|
+
if (!config.dimensions.hasOwnProperty(axis)) {
|
|
17
|
+
return () => {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const brushRangeMax =
|
|
21
|
+
config.dimensions[axis].type === 'string'
|
|
22
|
+
? config.dimensions[axis].yscale.range()[
|
|
23
|
+
config.dimensions[axis].yscale.range().length - 1
|
|
24
|
+
]
|
|
25
|
+
: config.dimensions[axis].yscale.range()[0];
|
|
26
|
+
|
|
27
|
+
const _brush = brushY(_selector).extent([[-15, 0], [15, brushRangeMax]]);
|
|
28
|
+
|
|
29
|
+
// d3 v6+ invokes listeners as (event, datum); the v5 (datum, index, nodes)
|
|
30
|
+
// layout this used to slice out of `arguments` no longer exists. The axis name
|
|
31
|
+
// is already in scope above, and the node is the listener's `this`.
|
|
32
|
+
const convertBrushArguments = node => {
|
|
33
|
+
const raw = brushSelection(node) || [];
|
|
34
|
+
|
|
35
|
+
// handle hidden axes which will not have a yscale
|
|
36
|
+
let yscale = null;
|
|
37
|
+
if (config.dimensions.hasOwnProperty(axis)) {
|
|
38
|
+
yscale = config.dimensions[axis].yscale;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ordinal scales do not have invert
|
|
42
|
+
const scaled = invertByScale(raw, yscale);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
axis,
|
|
46
|
+
node,
|
|
47
|
+
selection: {
|
|
48
|
+
raw,
|
|
49
|
+
scaled,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
_brush
|
|
55
|
+
.on('start', function(event) {
|
|
56
|
+
// d3 v6+ leaves sourceEvent undefined for a programmatic brush.move,
|
|
57
|
+
// where v5 set it to null; `!=` catches both.
|
|
58
|
+
if (event.sourceEvent != null) {
|
|
59
|
+
events.call(
|
|
60
|
+
'brushstart',
|
|
61
|
+
pc,
|
|
62
|
+
config.brushed,
|
|
63
|
+
convertBrushArguments(this)
|
|
64
|
+
);
|
|
65
|
+
if (typeof event.sourceEvent.stopPropagation === 'function') {
|
|
66
|
+
event.sourceEvent.stopPropagation();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
.on('brush', function() {
|
|
71
|
+
brushUpdated(
|
|
72
|
+
config,
|
|
73
|
+
pc,
|
|
74
|
+
events,
|
|
75
|
+
convertBrushArguments(this)
|
|
76
|
+
)(selected(state, config, brushGroup)());
|
|
77
|
+
})
|
|
78
|
+
.on('end', function() {
|
|
79
|
+
brushUpdated(config, pc, events)(selected(state, config, brushGroup)());
|
|
80
|
+
events.call(
|
|
81
|
+
'brushend',
|
|
82
|
+
pc,
|
|
83
|
+
config.brushed,
|
|
84
|
+
convertBrushArguments(this)
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
state.brushes[axis] = _brush;
|
|
89
|
+
state.brushNodes[axis] = _selector.node();
|
|
90
|
+
|
|
91
|
+
return _brush;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default brushFor;
|
|
@@ -1,102 +1,104 @@
|
|
|
1
|
-
import { brushY, brushSelection } from 'd3-brush';
|
|
2
|
-
import { select } from 'd3-selection';
|
|
3
|
-
import drawBrushes from './drawBrushes';
|
|
4
|
-
import selected from './selected';
|
|
5
|
-
|
|
6
|
-
const brushUpdated = (config, pc, events) => newSelection => {
|
|
7
|
-
config.brushed = newSelection;
|
|
8
|
-
events.call('brush', pc, config.brushed);
|
|
9
|
-
pc.renderBrushed();
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const newBrush = (state, config, pc, events, brushGroup) => (
|
|
13
|
-
axis,
|
|
14
|
-
_selector
|
|
15
|
-
) => {
|
|
16
|
-
const { brushes, brushNodes } = state;
|
|
17
|
-
|
|
18
|
-
const brushRangeMax =
|
|
19
|
-
config.dimensions[axis].type === 'string'
|
|
20
|
-
? config.dimensions[axis].yscale.range()[
|
|
21
|
-
config.dimensions[axis].yscale.range().length - 1
|
|
22
|
-
]
|
|
23
|
-
: config.dimensions[axis].yscale.range()[0];
|
|
24
|
-
|
|
25
|
-
const brush = brushY().extent([[-15, 0], [15, brushRangeMax]]);
|
|
26
|
-
const id = brushes[axis] ? brushes[axis].length : 0;
|
|
27
|
-
const node =
|
|
28
|
-
'brush-' + Object.keys(config.dimensions).indexOf(axis) + '-' + id;
|
|
29
|
-
|
|
30
|
-
if (brushes[axis]) {
|
|
31
|
-
brushes[axis].push({
|
|
32
|
-
id,
|
|
33
|
-
brush,
|
|
34
|
-
node,
|
|
35
|
-
});
|
|
36
|
-
} else {
|
|
37
|
-
brushes[axis] = [{ id, brush, node }];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (brushNodes[axis]) {
|
|
41
|
-
brushNodes[axis].push({ id, node });
|
|
42
|
-
} else {
|
|
43
|
-
brushNodes[axis] = [{ id, node }];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
brush
|
|
47
|
-
.on('start', function(event) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
selection
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
event.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
import { brushY, brushSelection } from 'd3-brush';
|
|
2
|
+
import { select } from 'd3-selection';
|
|
3
|
+
import drawBrushes from './drawBrushes';
|
|
4
|
+
import selected from './selected';
|
|
5
|
+
|
|
6
|
+
const brushUpdated = (config, pc, events) => newSelection => {
|
|
7
|
+
config.brushed = newSelection;
|
|
8
|
+
events.call('brush', pc, config.brushed);
|
|
9
|
+
pc.renderBrushed();
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const newBrush = (state, config, pc, events, brushGroup) => (
|
|
13
|
+
axis,
|
|
14
|
+
_selector
|
|
15
|
+
) => {
|
|
16
|
+
const { brushes, brushNodes } = state;
|
|
17
|
+
|
|
18
|
+
const brushRangeMax =
|
|
19
|
+
config.dimensions[axis].type === 'string'
|
|
20
|
+
? config.dimensions[axis].yscale.range()[
|
|
21
|
+
config.dimensions[axis].yscale.range().length - 1
|
|
22
|
+
]
|
|
23
|
+
: config.dimensions[axis].yscale.range()[0];
|
|
24
|
+
|
|
25
|
+
const brush = brushY().extent([[-15, 0], [15, brushRangeMax]]);
|
|
26
|
+
const id = brushes[axis] ? brushes[axis].length : 0;
|
|
27
|
+
const node =
|
|
28
|
+
'brush-' + Object.keys(config.dimensions).indexOf(axis) + '-' + id;
|
|
29
|
+
|
|
30
|
+
if (brushes[axis]) {
|
|
31
|
+
brushes[axis].push({
|
|
32
|
+
id,
|
|
33
|
+
brush,
|
|
34
|
+
node,
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
brushes[axis] = [{ id, brush, node }];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (brushNodes[axis]) {
|
|
41
|
+
brushNodes[axis].push({ id, node });
|
|
42
|
+
} else {
|
|
43
|
+
brushNodes[axis] = [{ id, node }];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
brush
|
|
47
|
+
.on('start', function(event) {
|
|
48
|
+
// d3 v6+ leaves sourceEvent undefined for a programmatic brush.move,
|
|
49
|
+
// where v5 set it to null; `!=` catches both.
|
|
50
|
+
if (event.sourceEvent != null) {
|
|
51
|
+
events.call('brushstart', pc, config.brushed);
|
|
52
|
+
if (typeof event.sourceEvent.stopPropagation === 'function') {
|
|
53
|
+
event.sourceEvent.stopPropagation();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.on('brush', function() {
|
|
58
|
+
// record selections
|
|
59
|
+
brushUpdated(
|
|
60
|
+
config,
|
|
61
|
+
pc,
|
|
62
|
+
events
|
|
63
|
+
)(selected(state, config, pc, events, brushGroup));
|
|
64
|
+
})
|
|
65
|
+
.on('end', function(event) {
|
|
66
|
+
// Figure out if our latest brush has a selection
|
|
67
|
+
const lastBrushID = brushes[axis][brushes[axis].length - 1].id;
|
|
68
|
+
const lastBrush = document.getElementById(
|
|
69
|
+
'brush-' +
|
|
70
|
+
Object.keys(config.dimensions).indexOf(axis) +
|
|
71
|
+
'-' +
|
|
72
|
+
lastBrushID
|
|
73
|
+
);
|
|
74
|
+
const selection = brushSelection(lastBrush);
|
|
75
|
+
|
|
76
|
+
if (
|
|
77
|
+
selection !== undefined &&
|
|
78
|
+
selection !== null &&
|
|
79
|
+
selection[0] !== selection[1]
|
|
80
|
+
) {
|
|
81
|
+
newBrush(state, config, pc, events, brushGroup)(axis, _selector);
|
|
82
|
+
|
|
83
|
+
drawBrushes(brushes[axis], config, pc, axis, _selector);
|
|
84
|
+
|
|
85
|
+
brushUpdated(config, pc, events)(
|
|
86
|
+
selected(state, config, pc, events, brushGroup)
|
|
87
|
+
);
|
|
88
|
+
} else {
|
|
89
|
+
if (
|
|
90
|
+
event.sourceEvent &&
|
|
91
|
+
event.sourceEvent.toString() === '[object MouseEvent]' &&
|
|
92
|
+
event.selection === null
|
|
93
|
+
) {
|
|
94
|
+
pc.brushReset(axis);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
events.call('brushend', pc, config.brushed);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return brush;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default newBrush;
|