Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for clearing selection #4720

Merged
merged 41 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7989028
added clear transform to files
Mar 11, 2019
958360c
added test suite and modified clear to not occur on default - must fl…
Mar 13, 2019
5821af8
adding single type support
Mar 15, 2019
ef5f6b8
adding test cases for single + interval clearing
Mar 15, 2019
dd06819
[Travis] Update examples (build: 22361)
Mar 15, 2019
de29ed0
Clear transform default doubleclick clears selected data and brush, w…
Mar 21, 2019
0c3d122
adding test cases for clear.ts and updating other test files to turn …
Mar 21, 2019
1505a1e
added clear transform to files
Mar 11, 2019
7249a10
added test suite and modified clear to not occur on default - must fl…
Mar 13, 2019
3cba482
adding single type support
Mar 15, 2019
d49d694
adding test cases for single + interval clearing
Mar 15, 2019
20eba3f
[Travis] Update examples (build: 22361)
Mar 15, 2019
cd6362a
Clear transform default doubleclick clears selected data and brush, w…
Mar 21, 2019
94027a9
adding test cases for clear.ts and updating other test files to turn …
Mar 21, 2019
f1f08d7
Merge branch 'ajl/clear' of https://github.com/vega/vega-lite into aj…
Mar 21, 2019
cb15c08
[Travis] Update schema (build: 22402)
Mar 21, 2019
2e8b2b5
[Travis] Update examples (build: 22402)
Mar 21, 2019
c9ab937
migrated clear to conditional config, and interval type clear now onl…
Apr 2, 2019
70b4ea3
Merge branch 'ajl/clear' of https://github.com/vega/vega-lite into aj…
Apr 2, 2019
e6335a1
adding clear transform documentation
Apr 2, 2019
d505802
Merge branch 'master' into ajl/clear
Apr 2, 2019
30857fe
[Travis] Update schema (build: 22802)
Apr 2, 2019
2ea1ead
[Travis] Update examples (build: 22802)
Apr 2, 2019
73777ca
simplified code a little
Apr 3, 2019
97ae4e3
Merge branch 'ajl/clear' of https://github.com/vega/vega-lite into aj…
Apr 3, 2019
ae4f8ae
clearing selection and panning/zooming, also updated docs and tests
Apr 3, 2019
3cdba25
[Travis] Update examples (build: 22820)
Apr 3, 2019
f0804b2
significantly refactored clear code
Apr 5, 2019
77aa146
Merge branch 'ajl/clear' of https://github.com/vega/vega-lite into aj…
Apr 5, 2019
d105409
updating TSDocs and Vega-lite docs
Apr 5, 2019
937aa9f
[Travis] Update examples (build: 22858)
Apr 5, 2019
1a3ec0c
Minor fixes to clear logic/style to minimize signal additions.
arvind Apr 5, 2019
053f24b
Append clear to top-level signals to account for input bindings.
arvind Apr 5, 2019
519a2b6
Refine documentation on selection clearing.
arvind Apr 5, 2019
6b81dd2
Selection clearing should account for toggling.
arvind Apr 5, 2019
b99ef92
[Travis] Update schema (build: 22868)
Apr 5, 2019
f6e9a88
[Travis] Update examples (build: 22868)
Apr 5, 2019
9455fb8
Fix backticks
kanitw Apr 6, 2019
e51e6ce
Rename `selection_clear_heatmap` to `selection_heatmap` as it doesn't…
kanitw Apr 6, 2019
165d8ca
Refactor selection_heatmap example + add it to the gallery
kanitw Apr 6, 2019
dd9d82e
[Travis] Update examples (build: 22876)
Apr 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/compile/selection/transforms/clear.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import {TUPLE} from '..';
import {selector as parseSelector} from 'vega-event-selector';
import {TransformCompiler} from './transforms';

const CLEAR_DATA_SIGNALS = [TUPLE, '_toggle'];
const CLEAR_VISUAL_SIGNALS = ['_x', '_y'];

const CLEAR_SIGNALS = [CLEAR_DATA_SIGNALS, CLEAR_VISUAL_SIGNALS];
const CLEAR_UPDATE = ['null', '[0, 0]'];

const clear: TransformCompiler = {
has: selCmpt => {
return selCmpt.clear;
},

signals: (model, selCmpt, signals) => {
const tupleIdx = signals.findIndex(i => i.name === selCmpt.name + TUPLE);
signals[tupleIdx].on.push({
events: [{source: 'scope', type: selCmpt.clear}],
update: 'null'
let events = parseSelector(selCmpt.clear, 'scope');
CLEAR_SIGNALS.forEach((signal, k) => {
for (let i = 0; i < signal.length; i++) {
const idx = signals.findIndex(n => n.name === selCmpt.name + signal[i]);
if (idx !== -1) {
signals[idx].on = signals[idx].on
? signals[idx].on.concat({
events: events,
update: CLEAR_UPDATE[k]
})
: [{events: events, update: CLEAR_UPDATE[k]}];
}
}
});
return signals;
}
Expand Down
18 changes: 4 additions & 14 deletions src/compile/selection/transforms/transforms.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {NewSignal, Signal} from 'vega';
import {SelectionComponent} from '..';
import {SelectionDef} from '../../../selection';
import {Dict} from '../../../util';
import {Model} from '../../model';
import {UnitModel} from '../../unit';
import clear from './clear';
Expand All @@ -22,21 +21,12 @@ export interface TransformCompiler {
marks?: (model: UnitModel, selCmpt: SelectionComponent, marks: any[]) => any[];
}

const compilers: Dict<TransformCompiler> = {
project,
toggle,
scales,
translate,
zoom,
inputs,
nearest,
clear
};
const compilers: Array<TransformCompiler> = [project, toggle, scales, translate, zoom, inputs, nearest, clear];

export function forEachTransform(selCmpt: SelectionComponent, cb: (tx: TransformCompiler) => void) {
for (const t in compilers) {
if (compilers[t].has(selCmpt)) {
cb(compilers[t]);
for (const t of compilers) {
if (t.has(selCmpt)) {
cb(t);
}
}
}
16 changes: 7 additions & 9 deletions src/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ export interface BaseSelectionDef {

export interface SingleSelectionConfig extends BaseSelectionDef {
/**
* Controls clearing selections. Can be `true`, `false`, or a `string` that is
* one of the [Supported Event Types](https://vega.github.io/vega/docs/event-streams/).
* Controls clearing selections. Can be `true`, `false`, or an [EventStream](https://vega.github.io/vega/docs/event-streams/).
*
* __Default value:__ `true`, which corresponds to `dblclick` (i.e.
* user doubleclick clears current selection).
*
* See the [TODO: clear] documentation for more information.
*/
clear?: string | boolean;
clear?: EventStream | boolean;
/**
* Establish a two-way binding between a single selection and input elements
* (also known as dynamic query widgets). A binding takes the form of
Expand All @@ -93,15 +92,14 @@ export interface SingleSelectionConfig extends BaseSelectionDef {

export interface MultiSelectionConfig extends BaseSelectionDef {
/**
* Controls clearing selections. Can be `true`, `false`, or a `string` that is
* one of the [Supported Event Types](https://vega.github.io/vega/docs/event-streams/).
* Controls clearing selections. Can be `true`, `false`, or an [EventStream](https://vega.github.io/vega/docs/event-streams/).
*
* __Default value:__ `true`, which corresponds to `dblclick` (i.e.
* user doubleclick clears current selection).
*
* See the [TODO: clear] documentation for more information.
*/
clear?: string | boolean;
clear?: EventStream | boolean;

/**
* Controls whether data values should be toggled or only ever inserted into
Expand Down Expand Up @@ -171,15 +169,14 @@ export interface BrushConfig {

export interface IntervalSelectionConfig extends BaseSelectionDef {
/**
* Controls clearing selections. Can be `true`, `false`, or a `string` that is
* one of the [Supported Event Types](https://vega.github.io/vega/docs/event-streams/).
* Controls clearing selections. Can be `true`, `false`, or an [EventStream](https://vega.github.io/vega/docs/event-streams/).
*
* __Default value:__ `true`, which corresponds to `dblclick` (i.e.
* user doubleclick clears current selection).
*
* See the [TODO: clear] documentation for more information.
*/
clear?: string | boolean;
clear?: EventStream | boolean;
/**
* When truthy, allows a user to interactively move an interval selection
* back-and-forth. Can be `true`, `false` (to disable panning), or a
Expand Down Expand Up @@ -272,6 +269,7 @@ export const defaultConfig: SelectionConfig = {
single: {
on: 'click',
fields: [SELECTION_ID],
clear: 'dblclick',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default clear should be mouseout if on is mouseover.

(But dblclick is good otherwise. Thus, I don't think dblclick should be defined here in config.) .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I don't think "interval" needs default "clear" given that click would be the default clear without an additional signal anyway. (Click triggers brush, and if you don't drag, that's equivalent to clearing.)

Copy link
Member

@arvind arvind Mar 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But dblclick is good otherwise. Thus, I don't think dblclick should be defined here in config.

Hmm, this is an interesting point. The default "on": "click" is defined in the configuration, so it seems to make sense to define clear consistently as well. But I see your point that if the user changed to "on": "mouseover" we might want to detect that and reflect it. If that's the only exception we can think of, I'd rather handle it separately, when we parse defaults, rather than not have clear defined in our SelectionConfig whatsoever.

Also, I don't think "interval" needs default "clear" given that click would be the default clear without an additional signal anyway.

I disagree. When an interval selection is bound to scales, it would be helpful to clear it to return to the original scale domains (so too if we had brush-to-zoom functionality as in #4742). Moreover, as much as possible, I would like to keep all selection types working consistently (that is, after all, our original vision of a grammar of interaction rather than a typology of selections).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is an interesting point. The default "on": "click" is defined in the configuration, so it seems to make sense to define clear consistently as well. But I see your point that if the user changed to "on": "mouseover" we might want to detect that and reflect it. If that's the only exception we can think of, I'd rather handle it separately, when we parse defaults, rather than not have clear defined in our SelectionConfig whatsoever.

In the rest of the language, we make the config undefined if the default value has condition rule. For example, we don't set opacity in mark config. Same for axis labelAngle.

When we want users to be able to customize config for each case, we then introduce a more specific version of config. For example, bandPaddingInner scale config is undefined (automatic) by default, but the automatic rule will draw value from barBandPaddingInner and rectBandPaddingInner scale configs. If users set bandPaddingInner scale config to a specific value, then the default value is fixed and barBandPaddingInner and rectBandPaddingInner are ignored.

So I think we should have consistent config design here.

When an interval selection is bound to scales, it would be helpful to clear it to return to the original scale domains

Good point. I agree.

Note that as I mentioned previously, I see the benefit of interaction typologies as a macro level on top of selection grammar and have started prototyping it a bit, but that's a different issue separate from this. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reply, I just got back to the US.

Is the intention to have clear non-conditionally defined, i.e. set default configs to dblclick and in cases where user changed to "on: "mouseover" they also need to change "clear": "mouseout". Or have it conditionally defined, making the config undefined and conditionally choosing the EventStream trigger based off of the on config?

If the latter, should I make these changes in this PR or in a follow-up?

Copy link
Member

@kanitw kanitw Apr 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries at all.

I mean the latter:

making the config undefined and conditionally choosing the EventStream trigger based on the on config

Since it's a simple change, let's do in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, don't forget to add clear to the docs. :)

resolve: 'global',
empty: 'all'
},
Expand Down