From bfc97d06488fa3a595da7a4c1f9f687760604a0b Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 11:05:48 +0530 Subject: [PATCH 01/14] Simplify selection project transform. --- src/compile/selection/interval.ts | 20 +++++------ src/compile/selection/multi.ts | 2 +- src/compile/selection/selection.ts | 20 +++++------ src/compile/selection/transforms/project.ts | 40 ++++++++++----------- src/compile/selection/transforms/scales.ts | 4 +-- test/compile/selection/parse.test.ts | 18 +++++----- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index eebf895142..988d386075 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -210,16 +210,16 @@ function channelSignals(model: UnitModel, selCmpt: SelectionComponent, channel: return hasScales ? [{name: dname, on: []}] : [ - { - name: vname, - value: [], - on: on - }, - { - name: dname, - on: [{events: {signal: vname}, update: `${vname}[0] === ${vname}[1] ? null : invert(${scaleStr}, ${vname})`}] - } - ]; + { + name: vname, + value: [], + on: on + }, + { + name: dname, + on: [{events: {signal: vname}, update: `${vname}[0] === ${vname}[1] ? null : invert(${scaleStr}, ${vname})`}] + } + ]; } function events(selCmpt: SelectionComponent, cb: (...args: any[]) => void) { diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index 5664a154bb..722e0d0dec 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -22,7 +22,7 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { return fieldDef && fieldDef.bin ? (bins.push(p.field), `[${accessPathWithDatum(model.vgField(channel, {}), datum)}, ` + - `${accessPathWithDatum(model.vgField(channel, {binSuffix: 'end'}), datum)}]`) + `${accessPathWithDatum(model.vgField(channel, {binSuffix: 'end'}), datum)}]`) : `${accessPathWithDatum(p.field, datum)}`; }) .join(', '); diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index f3e20acaea..14ccbd439c 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -1,7 +1,7 @@ import {SignalRef} from 'vega'; import {selector as parseSelector} from 'vega-event-selector'; import {isString, stringValue} from 'vega-util'; -import {Channel, ScaleChannel, X, Y} from '../../channel'; +import {Channel, ScaleChannel, SingleDefChannel, X, Y} from '../../channel'; import {warn} from '../../log'; import {LogicalOperand} from '../../logical'; import {BrushConfig, SELECTION_ID, SelectionDef, SelectionResolution, SelectionType} from '../../selection'; @@ -37,19 +37,19 @@ export interface SelectionComponent { _signalNames: {}; // Transforms - project?: ProjectComponent[]; - fields?: any; + project?: ProjectSelectionComponent[]; + fields?: {[c in SingleDefChannel]?: string}; timeUnit?: TimeUnitNode; - scales?: Channel[]; + scales?: ScaleChannel[]; toggle?: any; translate?: any; zoom?: any; nearest?: any; } -export interface ProjectComponent { +export interface ProjectSelectionComponent { field?: string; - channel?: ScaleChannel; + channel?: SingleDefChannel; } export interface SelectionCompiler { @@ -98,7 +98,7 @@ export function parseUnitSelection(model: UnitModel, selDefs: Dict ...selDef, name: name, events: isString(selDef.on) ? parseSelector(selDef.on, 'scope') : selDef.on - } as SelectionComponent); + } as any); forEachTransform(selCmpt, txCompiler => { if (txCompiler.parse) { @@ -279,7 +279,7 @@ export function selectionScaleDomain(model: Model, domainRaw: SignalRef): Signal if (selCmpt.project.length > 1) { warn( 'A "field" or "encoding" must be specified when using a selection as a scale domain. ' + - `Using "field": ${stringValue(selDomain.field)}.` + `Using "field": ${stringValue(selDomain.field)}.` ); } } @@ -368,9 +368,9 @@ export function channelSignalName(selCmpt: SelectionComponent, channel: Channel, } export function positionalProjections(selCmpt: SelectionComponent) { - let x: ProjectComponent = null; + let x: ProjectSelectionComponent = null; let xi: number = null; - let y: ProjectComponent = null; + let y: ProjectSelectionComponent = null; let yi: number = null; selCmpt.project.forEach((p, i) => { diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index f4a50b4f4d..6be355c8d8 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -3,7 +3,7 @@ import * as log from '../../../log'; import {SelectionDef} from '../../../selection'; import {keys} from '../../../util'; import {TimeUnitComponent, TimeUnitNode} from '../../data/timeunit'; -import {SelectionComponent} from '../selection'; +import {ProjectSelectionComponent, SelectionComponent} from '../selection'; import {TransformCompiler} from './transforms'; const project: TransformCompiler = { @@ -13,46 +13,46 @@ const project: TransformCompiler = { }, parse: (model, selDef, selCmpt) => { - const channels = {}; - const timeUnits: {[key: string]: TimeUnitComponent} = {}; + const timeUnits: {[field: string]: TimeUnitComponent} = {}; + const f: {[field: string]: ProjectSelectionComponent} = {}; + const p = selCmpt.project || (selCmpt.project = []); + selCmpt.fields = {}; // TODO: find a possible channel mapping for these fields. - (selDef.fields || []).forEach(field => (channels[field] = null)); + if (selDef.fields) { + p.push.apply(p, selDef.fields.map(field => ({field}))); + } (selDef.encodings || []).forEach((channel: SingleDefChannel) => { const fieldDef = model.fieldDef(channel); if (fieldDef) { + let field = fieldDef.field; if (fieldDef.timeUnit) { - const tuField = model.vgField(channel); - channels[tuField] = channel; + field = model.vgField(channel); // Construct TimeUnitComponents which will be combined into a // TimeUnitNode. This node may need to be inserted into the // dataflow if the selection is used across views that do not // have these time units defined. - timeUnits[tuField] = { - as: tuField, + timeUnits[field] = { + as: field, field: fieldDef.field, timeUnit: fieldDef.timeUnit }; - } else { - channels[fieldDef.field] = channel; } + + // Prevent duplicate projections on the same field. + // TODO: what if the same field is bound to multiple channels (e.g., SPLOM diag). + if (!f[field]) { + p.push(f[field] = {field, channel}); + } + + selCmpt.fields[channel] = field; } else { log.warn(log.message.cannotProjectOnChannelWithoutField(channel)); } }); - const projection = selCmpt.project || (selCmpt.project = []); - for (const field in channels) { - if (channels.hasOwnProperty(field)) { - projection.push({field: field, channel: channels[field]}); - } - } - - const fields = selCmpt.fields || (selCmpt.fields = {}); - projection.filter(p => p.channel).forEach(p => (fields[p.channel] = p.field)); - if (keys(timeUnits).length) { selCmpt.timeUnit = new TimeUnitNode(null, timeUnits); } diff --git a/src/compile/selection/transforms/scales.ts b/src/compile/selection/transforms/scales.ts index 230309a9fc..a496e93305 100644 --- a/src/compile/selection/transforms/scales.ts +++ b/src/compile/selection/transforms/scales.ts @@ -1,5 +1,5 @@ import {stringValue} from 'vega-util'; -import {Channel, X, Y} from '../../../channel'; +import {Channel, ScaleChannel, X, Y} from '../../../channel'; import * as log from '../../../log'; import {hasContinuousDomain, isBinScale} from '../../../scale'; import {UnitModel} from '../../unit'; @@ -15,7 +15,7 @@ const scaleBindings: TransformCompiler = { const bound: Channel[] = (selCmpt.scales = []); selCmpt.project.forEach(p => { - const channel = p.channel; + const channel = p.channel as ScaleChannel; const scale = model.getScaleComponent(channel); const scaleType = scale ? scale.get('type') : undefined; diff --git a/test/compile/selection/parse.test.ts b/test/compile/selection/parse.test.ts index 8caecea7ab..2d19496b42 100644 --- a/test/compile/selection/parse.test.ts +++ b/test/compile/selection/parse.test.ts @@ -27,20 +27,20 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: '_vgsid_', channel: null}]); + assert.sameDeepMembers(component['one'].project, [{field: '_vgsid_'}]); assert.sameDeepMembers(component['one'].events, parseSelector('click', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.shiftKey'); - assert.sameDeepMembers(component['two'].project, [{field: '_vgsid_', channel: null}]); + assert.sameDeepMembers(component['two'].project, [{field: '_vgsid_'}]); assert.sameDeepMembers(component['two'].events, parseSelector('click', 'scope')); assert.equal(component.three.name, 'three'); assert.equal(component.three.type, 'interval'); assert.equal(component.three.translate, '[mousedown, window:mouseup] > window:mousemove!'); assert.equal(component.three.zoom, 'wheel!'); - assert.sameDeepMembers(component['three'].project, [ + assert.sameDeepMembers(component['three'].project, [ {field: 'Horsepower', channel: 'x'}, {field: 'Miles_per_Gallon', channel: 'y'} ]); @@ -76,20 +76,20 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders', channel: null}]); + assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders'}]); assert.sameDeepMembers(component['one'].events, parseSelector('dblclick', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); + assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); assert.equal(component.three.type, 'interval'); assert.equal(component.three.translate, false); assert.equal(component.three.zoom, 'wheel[event.altKey]'); - assert.sameDeepMembers(component['three'].project, [ + assert.sameDeepMembers(component['three'].project, [ {field: 'Miles_per_Gallon', channel: 'y'} ]); assert.sameDeepMembers( @@ -119,20 +119,20 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders', channel: null}]); + assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders'}]); assert.sameDeepMembers(component['one'].events, parseSelector('dblclick', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); + assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); assert.equal(component.three.type, 'interval'); assert(!component.three.translate); assert.equal(component.three.zoom, 'wheel[event.altKey]'); - assert.sameDeepMembers(component['three'].project, [ + assert.sameDeepMembers(component['three'].project, [ {field: 'Miles_per_Gallon', channel: 'y'} ]); assert.sameDeepMembers( From 528c65c5f26d03bdde0ad4d3c21cfe4c85969e22 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 12:14:57 +0530 Subject: [PATCH 02/14] Add new top-level signal to define structure of selection tuples. This signal centralizes definition of whether selection tuples enumerate values or define ranges, and is the first step to unifying tuple structures across selection types. --- src/compile/selection/selection.ts | 4 + src/compile/selection/transforms/project.ts | 32 ++++++- test/compile/selection/interval.test.ts | 2 + test/compile/selection/parse.test.ts | 92 ++++++++++++++++++--- test/compile/selection/single.test.ts | 4 +- 5 files changed, 119 insertions(+), 15 deletions(-) diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index 14ccbd439c..61d7f667fd 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -47,9 +47,13 @@ export interface SelectionComponent { nearest?: any; } +// Do the selection tuples hold enumerated or ranged values for a field? +export type TupleStoreType = 'E' | 'R'; + export interface ProjectSelectionComponent { field?: string; channel?: SingleDefChannel; + type: TupleStoreType; } export interface SelectionCompiler { diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index 6be355c8d8..9bdea6e8ed 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -1,11 +1,14 @@ -import {SingleDefChannel} from '../../../channel'; +import {ScaleChannel, SingleDefChannel} from '../../../channel'; import * as log from '../../../log'; +import {hasContinuousDomain, isBinScale} from '../../../scale'; import {SelectionDef} from '../../../selection'; import {keys} from '../../../util'; import {TimeUnitComponent, TimeUnitNode} from '../../data/timeunit'; -import {ProjectSelectionComponent, SelectionComponent} from '../selection'; +import {ProjectSelectionComponent, SelectionComponent, TUPLE, TupleStoreType} from '../selection'; import {TransformCompiler} from './transforms'; +export const TUPLE_DEF = '_def'; + const project: TransformCompiler = { has: (selDef: SelectionComponent | SelectionDef) => { const def = selDef as SelectionDef; @@ -20,7 +23,7 @@ const project: TransformCompiler = { // TODO: find a possible channel mapping for these fields. if (selDef.fields) { - p.push.apply(p, selDef.fields.map(field => ({field}))); + p.push.apply(p, selDef.fields.map(field => ({field, type: 'E'}))); } (selDef.encodings || []).forEach((channel: SingleDefChannel) => { @@ -44,7 +47,20 @@ const project: TransformCompiler = { // Prevent duplicate projections on the same field. // TODO: what if the same field is bound to multiple channels (e.g., SPLOM diag). if (!f[field]) { - p.push(f[field] = {field, channel}); + // Determine whether the tuple will store enumerated or ranged values. + // Interval selections store ranges for continuous scales, and enumerations otherwise. + // Single/multi selections store ranges for binned fields, and enumerations otherwise. + let type: TupleStoreType = 'E'; + if (selCmpt.type === 'interval') { + const scaleType = model.getScaleComponent(channel as ScaleChannel).get('type'); + if (hasContinuousDomain(scaleType) && !isBinScale(scaleType)) { + type = 'R'; + } + } else if (fieldDef.bin) { + type = 'R'; + } + + p.push(f[field] = {field, channel, type}); } selCmpt.fields[channel] = field; @@ -56,6 +72,14 @@ const project: TransformCompiler = { if (keys(timeUnits).length) { selCmpt.timeUnit = new TimeUnitNode(null, timeUnits); } + }, + + topLevelSignals: (model, selCmpt, signals) => { + const name = selCmpt.name + TUPLE + TUPLE_DEF; + const hasSignal = signals.filter(s => s.name === name); + return hasSignal.length ? signals : signals.concat({ + name, update: `${JSON.stringify(selCmpt.project)}` + }); } }; diff --git a/test/compile/selection/interval.test.ts b/test/compile/selection/interval.test.ts index fe5f8c6344..69af4b0412 100644 --- a/test/compile/selection/interval.test.ts +++ b/test/compile/selection/interval.test.ts @@ -224,6 +224,8 @@ describe('Interval Selections', () => { } }); + model2.parseScale(); + const selCmpts2 = (model2.component.selection = selection.parseUnitSelection(model2, { one: { type: 'interval', diff --git a/test/compile/selection/parse.test.ts b/test/compile/selection/parse.test.ts index 2d19496b42..5677777334 100644 --- a/test/compile/selection/parse.test.ts +++ b/test/compile/selection/parse.test.ts @@ -16,6 +16,8 @@ describe('Selection', () => { } }); + model.parseScale(); + it('parses default selection definitions', () => { const component = selection.parseUnitSelection(model, { one: {type: 'single'}, @@ -27,13 +29,13 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: '_vgsid_'}]); + assert.sameDeepMembers(component['one'].project, [{field: '_vgsid_', type: 'E'}]); assert.sameDeepMembers(component['one'].events, parseSelector('click', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.shiftKey'); - assert.sameDeepMembers(component['two'].project, [{field: '_vgsid_'}]); + assert.sameDeepMembers(component['two'].project, [{field: '_vgsid_', type: 'E'}]); assert.sameDeepMembers(component['two'].events, parseSelector('click', 'scope')); assert.equal(component.three.name, 'three'); @@ -41,8 +43,8 @@ describe('Selection', () => { assert.equal(component.three.translate, '[mousedown, window:mouseup] > window:mousemove!'); assert.equal(component.three.zoom, 'wheel!'); assert.sameDeepMembers(component['three'].project, [ - {field: 'Horsepower', channel: 'x'}, - {field: 'Miles_per_Gallon', channel: 'y'} + {field: 'Horsepower', channel: 'x', type: 'R'}, + {field: 'Miles_per_Gallon', channel: 'y', type: 'R'} ]); assert.sameDeepMembers( component['three'].events, @@ -76,13 +78,13 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders'}]); + assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders', type: 'E'}]); assert.sameDeepMembers(component['one'].events, parseSelector('dblclick', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); + assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color', type: 'E'}]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); @@ -90,7 +92,7 @@ describe('Selection', () => { assert.equal(component.three.translate, false); assert.equal(component.three.zoom, 'wheel[event.altKey]'); assert.sameDeepMembers(component['three'].project, [ - {field: 'Miles_per_Gallon', channel: 'y'} + {field: 'Miles_per_Gallon', channel: 'y', type: 'R'} ]); assert.sameDeepMembers( component['three'].events, @@ -119,13 +121,13 @@ describe('Selection', () => { assert.equal(component.one.name, 'one'); assert.equal(component.one.type, 'single'); - assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders'}]); + assert.sameDeepMembers(component['one'].project, [{field: 'Cylinders', type: 'E'}]); assert.sameDeepMembers(component['one'].events, parseSelector('dblclick', 'scope')); assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color'}]); + assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color', type: 'E'}]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); @@ -133,11 +135,81 @@ describe('Selection', () => { assert(!component.three.translate); assert.equal(component.three.zoom, 'wheel[event.altKey]'); assert.sameDeepMembers(component['three'].project, [ - {field: 'Miles_per_Gallon', channel: 'y'} + {field: 'Miles_per_Gallon', channel: 'y', type: 'R'} ]); assert.sameDeepMembers( component['three'].events, parseSelector('[mousedown[!event.shiftKey], mouseup] > mousemove', 'scope') ); }); + + describe('Projection', () => { + it('uses enumerated types for interval selections', () => { + let m = parseUnitModel({ + mark: 'circle', + encoding: { + x: {field: 'Origin', type: 'nominal'}, + y: {field: 'Miles_per_Gallon', type: 'quantitative'} + } + }); + + m.parseScale(); + + let c = selection.parseUnitSelection(m, { + one: {type: 'interval', encodings: ['x']} + }); + + assert.sameDeepMembers(c['one'].project, [{field: 'Origin', channel: 'x', type: 'E'}]); + + m = parseUnitModel({ + mark: 'bar', + encoding: { + x: {field: 'Origin', type: 'nominal'}, + y: {field: 'Miles_per_Gallon', type: 'quantitative'} + } + }); + + m.parseScale(); + + c = selection.parseUnitSelection(m, { + one: {type: 'interval', encodings: ['x']} + }); + + assert.sameDeepMembers(c['one'].project, [{field: 'Origin', channel: 'x', type: 'E'}]); + }); + + it('uses ranged types for single/multi selections', () => { + let m = parseUnitModel({ + mark: 'circle', + encoding: { + x: {field: 'Acceleration', type: 'quantitative', bin: true}, + y: {field: 'Miles_per_Gallon', type: 'quantitative'} + } + }); + + m.parseScale(); + + let c = selection.parseUnitSelection(m, { + one: {type: 'single', encodings: ['x']} + }); + + assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R'}]); + + m = parseUnitModel({ + mark: 'bar', + encoding: { + x: {field: 'Acceleration', type: 'quantitative', bin: true}, + y: {field: 'Miles_per_Gallon', type: 'quantitative'} + } + }); + + m.parseScale(); + + c = selection.parseUnitSelection(m, { + one: {type: 'multi', encodings: ['x']} + }); + + assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R'}]); + }); + }); }); diff --git a/test/compile/selection/single.test.ts b/test/compile/selection/single.test.ts index e5b1482a1d..b32a872561 100644 --- a/test/compile/selection/single.test.ts +++ b/test/compile/selection/single.test.ts @@ -15,6 +15,8 @@ describe('Single Selection', () => { } }); + model.parseScale(); + const selCmpts = (model.component.selection = selection.parseUnitSelection(model, { one: {type: 'single'}, two: { @@ -111,7 +113,7 @@ describe('Single Selection', () => { ]); const signals = selection.assembleTopLevelSignals(model, []); - assert.deepEqual( + assert.includeDeepMembers( signals, [ { From 9da4916c377cd3681eb794d911e1d468ecb1d6f2 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 12:26:34 +0530 Subject: [PATCH 03/14] Simplify single/multi selection tuple definition. Removing information now encapsulated by the tuple definition signal (82033613d). --- src/compile/selection/multi.ts | 36 ++++++++------------------- test/compile/selection/multi.test.ts | 4 +-- test/compile/selection/single.test.ts | 4 +-- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index 722e0d0dec..b7f14a70b6 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -1,5 +1,3 @@ -import {stringValue} from 'vega-util'; - import {accessPathWithDatum} from '../../util'; import {UnitModel} from '../unit'; import {SelectionCompiler, SelectionComponent, TUPLE, unitName} from './selection'; @@ -8,24 +6,14 @@ import nearest from './transforms/nearest'; export function signals(model: UnitModel, selCmpt: SelectionComponent) { const proj = selCmpt.project; const datum = nearest.has(selCmpt) ? '(item().isVoronoi ? datum.datum : datum)' : 'datum'; - const bins: string[] = []; - const encodings = proj - .map(p => stringValue(p.channel)) - .filter(e => e) - .join(', '); - const fields = proj.map(p => stringValue(p.field)).join(', '); - const values = proj - .map(p => { - const channel = p.channel; - const fieldDef = model.fieldDef(channel); - // Binned fields should capture extents, for a range test against the raw field. - return fieldDef && fieldDef.bin - ? (bins.push(p.field), - `[${accessPathWithDatum(model.vgField(channel, {}), datum)}, ` + - `${accessPathWithDatum(model.vgField(channel, {binSuffix: 'end'}), datum)}]`) - : `${accessPathWithDatum(p.field, datum)}`; - }) - .join(', '); + const values = proj.map(p => { + const fieldDef = model.fieldDef(p.channel); + // Binned fields should capture extents, for a range test against the raw field. + return fieldDef && fieldDef.bin + ? (`[${accessPathWithDatum(model.vgField(p.channel, {}), datum)}, ` + + `${accessPathWithDatum(model.vgField(p.channel, {binSuffix: 'end'}), datum)}]`) + : `${accessPathWithDatum(p.field, datum)}`; + }).join(', '); // Only add a discrete selection to the store if a datum is present _and_ // the interaction isn't occurring on a group mark. This guards against @@ -41,12 +29,8 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { on: [ { events: selCmpt.events, - update: - `datum && item().mark.marktype !== 'group' ? ` + - `{unit: ${unitName(model)}, encodings: [${encodings}], ` + - `fields: [${fields}], values: [${values}]` + - (bins.length ? ', ' + bins.map(b => `${stringValue('bin_' + b)}: 1`).join(', ') : '') + - '} : null', + update: `datum && item().mark.marktype !== 'group' ? ` + + `{unit: ${unitName(model)}, values: [${values}]} : null`, force: true } ] diff --git a/test/compile/selection/multi.test.ts b/test/compile/selection/multi.test.ts index 7ec9326b5b..bcf221946d 100644 --- a/test/compile/selection/multi.test.ts +++ b/test/compile/selection/multi.test.ts @@ -36,7 +36,7 @@ describe('Multi Selection', () => { { events: selCmpts['one'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", encodings: [], fields: ["_vgsid_"], values: [datum["_vgsid_"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [datum["_vgsid_"]]} : null', force: true } ] @@ -52,7 +52,7 @@ describe('Multi Selection', () => { { events: selCmpts['two'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", encodings: ["y", "color"], fields: ["Miles_per_Gallon", "Origin"], values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]], "bin_Miles_per_Gallon": 1} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', force: true } ] diff --git a/test/compile/selection/single.test.ts b/test/compile/selection/single.test.ts index b32a872561..6b398ba244 100644 --- a/test/compile/selection/single.test.ts +++ b/test/compile/selection/single.test.ts @@ -37,7 +37,7 @@ describe('Single Selection', () => { { events: selCmpts['one'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", encodings: [], fields: ["_vgsid_"], values: [datum["_vgsid_"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [datum["_vgsid_"]]} : null', force: true } ] @@ -53,7 +53,7 @@ describe('Single Selection', () => { { events: selCmpts['two'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", encodings: ["y", "color"], fields: ["Miles_per_Gallon", "Origin"], values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]], "bin_Miles_per_Gallon": 1} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', force: true } ] From 70e5efeb96ac9ef3e7902649809856251bcc0eeb Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 12:43:25 +0530 Subject: [PATCH 04/14] Align interval selection tuples with single/multi. --- src/compile/selection/interval.ts | 12 +++++------- test/compile/selection/interval.test.ts | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index 988d386075..5991ff9647 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -27,8 +27,7 @@ const interval: SelectionCompiler = { const name = selCmpt.name; const hasScales = scales.has(selCmpt); const signals: any[] = []; - const intervals: any[] = []; - const tupleTriggers: string[] = []; + const dataSignals: string[] = []; const scaleTriggers: any[] = []; if (selCmpt.translate && !hasScales) { @@ -56,8 +55,7 @@ const interval: SelectionCompiler = { const toNum = hasContinuousDomain(scaleType) ? '+' : ''; signals.push.apply(signals, cs); - tupleTriggers.push(dname); - intervals.push(`{encoding: ${stringValue(channel)}, ` + `field: ${stringValue(p.field)}, extent: ${dname}}`); + dataSignals.push(dname); scaleTriggers.push({ scaleName: model.scaleName(channel), @@ -84,9 +82,9 @@ const interval: SelectionCompiler = { name: name + TUPLE, on: [ { - events: tupleTriggers.map(t => ({signal: t})), - update: - tupleTriggers.join(' && ') + ` ? {unit: ${unitName(model)}, intervals: [${intervals.join(', ')}]} : null` + events: dataSignals.map(t => ({signal: t})), + update: dataSignals.join(' && ') + + ` ? {unit: ${unitName(model)}, values: [${dataSignals.join(', ')}]} : null` } ] }); diff --git a/test/compile/selection/interval.test.ts b/test/compile/selection/interval.test.ts index 69af4b0412..5cddd59ef5 100644 --- a/test/compile/selection/interval.test.ts +++ b/test/compile/selection/interval.test.ts @@ -180,7 +180,7 @@ describe('Interval Selections', () => { { events: [{signal: 'one_Horsepower'}], update: - 'one_Horsepower ? {unit: "", intervals: [{encoding: "x", field: "Horsepower", extent: one_Horsepower}]} : null' + 'one_Horsepower ? {unit: "", values: [one_Horsepower]} : null' } ] } @@ -194,7 +194,7 @@ describe('Interval Selections', () => { { events: [{signal: 'two_Miles_per_Gallon'}], update: - 'two_Miles_per_Gallon ? {unit: "", intervals: [{encoding: "y", field: "Miles-per-Gallon", extent: two_Miles_per_Gallon}]} : null' + 'two_Miles_per_Gallon ? {unit: "", values: [two_Miles_per_Gallon]} : null' } ] } @@ -208,7 +208,7 @@ describe('Interval Selections', () => { { events: [{signal: 'thr_ee_Horsepower'}, {signal: 'thr_ee_Miles_per_Gallon'}], update: - 'thr_ee_Horsepower && thr_ee_Miles_per_Gallon ? {unit: "", intervals: [{encoding: "x", field: "Horsepower", extent: thr_ee_Horsepower}, {encoding: "y", field: "Miles-per-Gallon", extent: thr_ee_Miles_per_Gallon}]} : null' + 'thr_ee_Horsepower && thr_ee_Miles_per_Gallon ? {unit: "", values: [thr_ee_Horsepower, thr_ee_Miles_per_Gallon]} : null' } ] } From 666bf7b41d4cd364d584f2a7cf0c7c7b0ad56525 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 13:25:00 +0530 Subject: [PATCH 05/14] Differentiate between inclusive/exclusive ranges. Interval selections define inclusive ranges. Discrete bin selections, however, should define a right-exclusive range, i.e., in the range [bin_start, bin_end). --- src/compile/selection/selection.ts | 3 ++- src/compile/selection/transforms/project.ts | 2 +- test/compile/selection/parse.test.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index 61d7f667fd..60f93fbd43 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -48,7 +48,8 @@ export interface SelectionComponent { } // Do the selection tuples hold enumerated or ranged values for a field? -export type TupleStoreType = 'E' | 'R'; +// Ranged values can be left-right inclusive (R) or left-inclusive, right-exclusive (R-LE). +export type TupleStoreType = 'E' | 'R' | 'R-RE'; export interface ProjectSelectionComponent { field?: string; diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index 9bdea6e8ed..34c49521d5 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -57,7 +57,7 @@ const project: TransformCompiler = { type = 'R'; } } else if (fieldDef.bin) { - type = 'R'; + type = 'R-RE'; } p.push(f[field] = {field, channel, type}); diff --git a/test/compile/selection/parse.test.ts b/test/compile/selection/parse.test.ts index 5677777334..47c5d2fa89 100644 --- a/test/compile/selection/parse.test.ts +++ b/test/compile/selection/parse.test.ts @@ -193,7 +193,7 @@ describe('Selection', () => { one: {type: 'single', encodings: ['x']} }); - assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R'}]); + assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R-RE'}]); m = parseUnitModel({ mark: 'bar', @@ -209,7 +209,7 @@ describe('Selection', () => { one: {type: 'multi', encodings: ['x']} }); - assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R'}]); + assert.sameDeepMembers(c['one'].project, [{field: 'Acceleration', channel: 'x', type: 'R-RE'}]); }); }); }); From 94421e6c4123559cbf47334c48daf8b174bf1a50 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 14:42:41 +0530 Subject: [PATCH 06/14] Use a standard predicate test expr function for all selection types. A standard tuple structure for all selection types means we no longer need the separate predicate test functions. --- src/compile/selection/interval.ts | 1 - src/compile/selection/multi.ts | 1 - src/compile/selection/selection.ts | 7 ++-- src/compile/selection/single.ts | 1 - test/compile/selection/predicate.test.ts | 52 ++++++++++++------------ test/compile/selection/timeunit.test.ts | 2 +- 6 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index 5991ff9647..7f2de5be04 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -20,7 +20,6 @@ export const BRUSH = '_brush'; export const SCALE_TRIGGER = '_scale_trigger'; const interval: SelectionCompiler = { - predicate: 'vlInterval', scaleDomain: 'vlIntervalDomain', signals: (model, selCmpt) => { diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index b7f14a70b6..3e09578de0 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -39,7 +39,6 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { } const multi: SelectionCompiler = { - predicate: 'vlMulti', scaleDomain: 'vlMultiDomain', signals: signals, diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index 60f93fbd43..c7d8796e47 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -17,6 +17,7 @@ import intervalCompiler from './interval'; import multiCompiler from './multi'; import {SelectionComponent} from './selection'; import singleCompiler from './single'; +import {TUPLE_DEF} from './transforms/project'; import {forEachTransform} from './transforms/transforms'; export const STORE = '_store'; @@ -62,7 +63,6 @@ export interface SelectionCompiler { topLevelSignals?: (model: Model, selCmpt: SelectionComponent, signals: any[]) => any[]; modifyExpr: (model: UnitModel, selCmpt: SelectionComponent) => string; marks?: (model: UnitModel, selCmpt: SelectionComponent, marks: any[]) => any[]; - predicate: string; // Vega expr string to determine inclusion in selection. scaleDomain: string; // Vega expr string to materialize a scale domain. } @@ -233,6 +233,7 @@ export function selectionPredicate(model: Model, selections: LogicalOperand { }); it('generates the predicate expression', () => { - assert.equal(predicate(model, 'one'), '!(length(data("one_store"))) || (vlSingle("one_store", datum))'); + assert.equal(predicate(model, 'one'), '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))'); - assert.equal(predicate(model, 'four'), '(vlSingle("four_store", datum))'); + assert.equal(predicate(model, 'four'), '(vlSelectionTest("four_store", four_tuple_def, datum))'); - assert.equal(predicate(model, {not: 'one'}), '!(length(data("one_store"))) || (!(vlSingle("one_store", datum)))'); + assert.equal(predicate(model, {not: 'one'}), '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", one_tuple_def, datum)))'); assert.equal( predicate(model, {not: {and: ['one', 'two']}}), '!(length(data("one_store")) || length(data("two_store"))) || ' + - '(!((vlSingle("one_store", datum)) && ' + - '(vlMulti("two_store", datum, "union"))))' + '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + + '(vlSelectionTest("two_store", two_tuple_def, datum, "union"))))' ); assert.equal( predicate(model, {not: {and: ['one', 'four']}}), - '!(length(data("one_store"))) || ' + '(!((vlSingle("one_store", datum)) && ' + '(vlSingle("four_store", datum))))' + '!(length(data("one_store"))) || ' + '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + '(vlSelectionTest("four_store", four_tuple_def, datum))))' ); assert.equal( predicate(model, {and: ['one', 'two', {not: 'thr-ee'}]}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSingle("one_store", datum)) && ' + - '(vlMulti("two_store", datum, "union")) && ' + - '(!(vlInterval("thr_ee_store", datum, "intersect"))))' + '((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + + '(vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect"))))' ); assert.equal( predicate(model, {or: ['one', {and: ['two', {not: 'thr-ee'}]}]}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSingle("one_store", datum)) || ' + - '((vlMulti("two_store", datum, "union")) && ' + - '(!(vlInterval("thr_ee_store", datum, "intersect")))))' + '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + + '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))' ); }); it('generates Vega production rules', () => { assert.deepEqual(nonPosition('color', model, {vgChannel: 'fill'}), { fill: [ - {test: '!(length(data("one_store"))) || (vlSingle("one_store", datum))', value: 'grey'}, + {test: '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))', value: 'grey'}, {scale: 'color', field: 'Cylinders'} ] }); @@ -92,9 +92,9 @@ describe('Selection Predicate', () => { { test: '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSingle("one_store", datum)) || ' + - '((vlMulti("two_store", datum, "union")) && ' + - '(!(vlInterval("thr_ee_store", datum, "intersect")))))', + '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + + '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))', value: 0.5 }, {scale: 'opacity', field: 'Origin'} @@ -105,35 +105,35 @@ describe('Selection Predicate', () => { it('generates a selection filter', () => { assert.equal( expression(model, {selection: 'one'}), - '!(length(data("one_store"))) || (vlSingle("one_store", datum))' + '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))' ); assert.equal( expression(model, {selection: {not: 'one'}}), - '!(length(data("one_store"))) || (!(vlSingle("one_store", datum)))' + '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", one_tuple_def, datum)))' ); assert.equal( expression(model, {selection: {not: {and: ['one', 'two']}}}), '!(length(data("one_store")) || length(data("two_store"))) || ' + - '(!((vlSingle("one_store", datum)) && ' + - '(vlMulti("two_store", datum, "union"))))' + '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + + '(vlSelectionTest("two_store", two_tuple_def, datum, "union"))))' ); assert.equal( expression(model, {selection: {and: ['one', 'two', {not: 'thr-ee'}]}}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSingle("one_store", datum)) && ' + - '(vlMulti("two_store", datum, "union")) && ' + - '(!(vlInterval("thr_ee_store", datum, "intersect"))))' + '((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + + '(vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect"))))' ); assert.equal( expression(model, {selection: {or: ['one', {and: ['two', {not: 'thr-ee'}]}]}}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSingle("one_store", datum)) || ' + - '((vlMulti("two_store", datum, "union")) && ' + - '(!(vlInterval("thr_ee_store", datum, "intersect")))))' + '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + + '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))' ); }); diff --git a/test/compile/selection/timeunit.test.ts b/test/compile/selection/timeunit.test.ts index a9c1309693..da347537ce 100644 --- a/test/compile/selection/timeunit.test.ts +++ b/test/compile/selection/timeunit.test.ts @@ -113,7 +113,7 @@ describe('Selection time unit', () => { }); data1.forEach((tx, idx) => { - if (tx.type === 'filter' && tx.expr.indexOf('vlSingle') >= 0) { + if (tx.type === 'filter' && tx.expr.indexOf('vlSelectionTest') >= 0) { selIdx = idx; } }); From 93c80915cc6e16c679e6f4d66b4dbd9ba892c4ec Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 15:00:52 +0530 Subject: [PATCH 07/14] Store field defs on selection tuple rather than a top-level signal. A top-level signal does not account for different views having different field/channel/type bindings for the same selection. --- src/compile/selection/interval.ts | 5 +- src/compile/selection/multi.ts | 7 ++- src/compile/selection/selection.ts | 4 +- src/compile/selection/transforms/project.ts | 6 +-- test/compile/selection/interval.test.ts | 6 +-- test/compile/selection/multi.test.ts | 4 +- test/compile/selection/predicate.test.ts | 52 ++++++++++----------- test/compile/selection/single.test.ts | 4 +- 8 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index 7f2de5be04..4ea464b343 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -14,6 +14,7 @@ import { TUPLE, unitName } from './selection'; +import {TUPLE_FIELDS} from './transforms/project'; import scales from './transforms/scales'; export const BRUSH = '_brush'; @@ -24,6 +25,7 @@ const interval: SelectionCompiler = { signals: (model, selCmpt) => { const name = selCmpt.name; + const fieldsSg = name + TUPLE + TUPLE_FIELDS; const hasScales = scales.has(selCmpt); const signals: any[] = []; const dataSignals: string[] = []; @@ -83,7 +85,8 @@ const interval: SelectionCompiler = { { events: dataSignals.map(t => ({signal: t})), update: dataSignals.join(' && ') + - ` ? {unit: ${unitName(model)}, values: [${dataSignals.join(', ')}]} : null` + ` ? {unit: ${unitName(model)}, fields: ${fieldsSg}, ` + + `values: [${dataSignals.join(', ')}]} : null` } ] }); diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index 3e09578de0..a5b03a3090 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -2,8 +2,11 @@ import {accessPathWithDatum} from '../../util'; import {UnitModel} from '../unit'; import {SelectionCompiler, SelectionComponent, TUPLE, unitName} from './selection'; import nearest from './transforms/nearest'; +import {TUPLE_FIELDS} from './transforms/project'; export function signals(model: UnitModel, selCmpt: SelectionComponent) { + const name = selCmpt.name; + const fieldsSg = name + TUPLE + TUPLE_FIELDS; const proj = selCmpt.project; const datum = nearest.has(selCmpt) ? '(item().isVoronoi ? datum.datum : datum)' : 'datum'; const values = proj.map(p => { @@ -24,13 +27,13 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { // be cleared on the second click). return [ { - name: selCmpt.name + TUPLE, + name: name + TUPLE, value: {}, on: [ { events: selCmpt.events, update: `datum && item().mark.marktype !== 'group' ? ` + - `{unit: ${unitName(model)}, values: [${values}]} : null`, + `{unit: ${unitName(model)}, fields: ${fieldsSg}, values: [${values}]} : null`, force: true } ] diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index c7d8796e47..fee8c3c04a 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -17,7 +17,6 @@ import intervalCompiler from './interval'; import multiCompiler from './multi'; import {SelectionComponent} from './selection'; import singleCompiler from './single'; -import {TUPLE_DEF} from './transforms/project'; import {forEachTransform} from './transforms/transforms'; export const STORE = '_store'; @@ -233,7 +232,6 @@ export function selectionPredicate(model: Model, selections: LogicalOperand { @@ -74,8 +74,8 @@ const project: TransformCompiler = { } }, - topLevelSignals: (model, selCmpt, signals) => { - const name = selCmpt.name + TUPLE + TUPLE_DEF; + signals: (model, selCmpt, signals) => { + const name = selCmpt.name + TUPLE + TUPLE_FIELDS; const hasSignal = signals.filter(s => s.name === name); return hasSignal.length ? signals : signals.concat({ name, update: `${JSON.stringify(selCmpt.project)}` diff --git a/test/compile/selection/interval.test.ts b/test/compile/selection/interval.test.ts index 5cddd59ef5..939553e48f 100644 --- a/test/compile/selection/interval.test.ts +++ b/test/compile/selection/interval.test.ts @@ -180,7 +180,7 @@ describe('Interval Selections', () => { { events: [{signal: 'one_Horsepower'}], update: - 'one_Horsepower ? {unit: "", values: [one_Horsepower]} : null' + 'one_Horsepower ? {unit: "", fields: one_tuple_fields, values: [one_Horsepower]} : null' } ] } @@ -194,7 +194,7 @@ describe('Interval Selections', () => { { events: [{signal: 'two_Miles_per_Gallon'}], update: - 'two_Miles_per_Gallon ? {unit: "", values: [two_Miles_per_Gallon]} : null' + 'two_Miles_per_Gallon ? {unit: "", fields: two_tuple_fields, values: [two_Miles_per_Gallon]} : null' } ] } @@ -208,7 +208,7 @@ describe('Interval Selections', () => { { events: [{signal: 'thr_ee_Horsepower'}, {signal: 'thr_ee_Miles_per_Gallon'}], update: - 'thr_ee_Horsepower && thr_ee_Miles_per_Gallon ? {unit: "", values: [thr_ee_Horsepower, thr_ee_Miles_per_Gallon]} : null' + 'thr_ee_Horsepower && thr_ee_Miles_per_Gallon ? {unit: "", fields: thr_ee_tuple_fields, values: [thr_ee_Horsepower, thr_ee_Miles_per_Gallon]} : null' } ] } diff --git a/test/compile/selection/multi.test.ts b/test/compile/selection/multi.test.ts index bcf221946d..cf32a65c5c 100644 --- a/test/compile/selection/multi.test.ts +++ b/test/compile/selection/multi.test.ts @@ -36,7 +36,7 @@ describe('Multi Selection', () => { { events: selCmpts['one'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [datum["_vgsid_"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", fields: one_tuple_fields, values: [datum["_vgsid_"]]} : null', force: true } ] @@ -52,7 +52,7 @@ describe('Multi Selection', () => { { events: selCmpts['two'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", fields: two_tuple_fields, values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', force: true } ] diff --git a/test/compile/selection/predicate.test.ts b/test/compile/selection/predicate.test.ts index a75cc8ea65..c35cff9928 100644 --- a/test/compile/selection/predicate.test.ts +++ b/test/compile/selection/predicate.test.ts @@ -44,45 +44,45 @@ describe('Selection Predicate', () => { }); it('generates the predicate expression', () => { - assert.equal(predicate(model, 'one'), '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))'); + assert.equal(predicate(model, 'one'), '!(length(data("one_store"))) || (vlSelectionTest("one_store", datum))'); - assert.equal(predicate(model, 'four'), '(vlSelectionTest("four_store", four_tuple_def, datum))'); + assert.equal(predicate(model, 'four'), '(vlSelectionTest("four_store", datum))'); - assert.equal(predicate(model, {not: 'one'}), '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", one_tuple_def, datum)))'); + assert.equal(predicate(model, {not: 'one'}), '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", datum)))'); assert.equal( predicate(model, {not: {and: ['one', 'two']}}), '!(length(data("one_store")) || length(data("two_store"))) || ' + - '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + - '(vlSelectionTest("two_store", two_tuple_def, datum, "union"))))' + '(!((vlSelectionTest("one_store", datum)) && ' + + '(vlSelectionTest("two_store", datum, "union"))))' ); assert.equal( predicate(model, {not: {and: ['one', 'four']}}), - '!(length(data("one_store"))) || ' + '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + '(vlSelectionTest("four_store", four_tuple_def, datum))))' + '!(length(data("one_store"))) || ' + '(!((vlSelectionTest("one_store", datum)) && ' + '(vlSelectionTest("four_store", datum))))' ); assert.equal( predicate(model, {and: ['one', 'two', {not: 'thr-ee'}]}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + - '(vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + - '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect"))))' + '((vlSelectionTest("one_store", datum)) && ' + + '(vlSelectionTest("two_store", datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", datum, "intersect"))))' ); assert.equal( predicate(model, {or: ['one', {and: ['two', {not: 'thr-ee'}]}]}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + - '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + - '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))' + '((vlSelectionTest("one_store", datum)) || ' + + '((vlSelectionTest("two_store", datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", datum, "intersect")))))' ); }); it('generates Vega production rules', () => { assert.deepEqual(nonPosition('color', model, {vgChannel: 'fill'}), { fill: [ - {test: '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))', value: 'grey'}, + {test: '!(length(data("one_store"))) || (vlSelectionTest("one_store", datum))', value: 'grey'}, {scale: 'color', field: 'Cylinders'} ] }); @@ -92,9 +92,9 @@ describe('Selection Predicate', () => { { test: '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + - '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + - '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))', + '((vlSelectionTest("one_store", datum)) || ' + + '((vlSelectionTest("two_store", datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", datum, "intersect")))))', value: 0.5 }, {scale: 'opacity', field: 'Origin'} @@ -105,35 +105,35 @@ describe('Selection Predicate', () => { it('generates a selection filter', () => { assert.equal( expression(model, {selection: 'one'}), - '!(length(data("one_store"))) || (vlSelectionTest("one_store", one_tuple_def, datum))' + '!(length(data("one_store"))) || (vlSelectionTest("one_store", datum))' ); assert.equal( expression(model, {selection: {not: 'one'}}), - '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", one_tuple_def, datum)))' + '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", datum)))' ); assert.equal( expression(model, {selection: {not: {and: ['one', 'two']}}}), '!(length(data("one_store")) || length(data("two_store"))) || ' + - '(!((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + - '(vlSelectionTest("two_store", two_tuple_def, datum, "union"))))' + '(!((vlSelectionTest("one_store", datum)) && ' + + '(vlSelectionTest("two_store", datum, "union"))))' ); assert.equal( expression(model, {selection: {and: ['one', 'two', {not: 'thr-ee'}]}}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSelectionTest("one_store", one_tuple_def, datum)) && ' + - '(vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + - '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect"))))' + '((vlSelectionTest("one_store", datum)) && ' + + '(vlSelectionTest("two_store", datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", datum, "intersect"))))' ); assert.equal( expression(model, {selection: {or: ['one', {and: ['two', {not: 'thr-ee'}]}]}}), '!(length(data("one_store")) || length(data("two_store")) || length(data("thr_ee_store"))) || ' + - '((vlSelectionTest("one_store", one_tuple_def, datum)) || ' + - '((vlSelectionTest("two_store", two_tuple_def, datum, "union")) && ' + - '(!(vlSelectionTest("thr_ee_store", thr_ee_tuple_def, datum, "intersect")))))' + '((vlSelectionTest("one_store", datum)) || ' + + '((vlSelectionTest("two_store", datum, "union")) && ' + + '(!(vlSelectionTest("thr_ee_store", datum, "intersect")))))' ); }); diff --git a/test/compile/selection/single.test.ts b/test/compile/selection/single.test.ts index 6b398ba244..644864b62e 100644 --- a/test/compile/selection/single.test.ts +++ b/test/compile/selection/single.test.ts @@ -37,7 +37,7 @@ describe('Single Selection', () => { { events: selCmpts['one'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [datum["_vgsid_"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", fields: one_tuple_fields, values: [datum["_vgsid_"]]} : null', force: true } ] @@ -53,7 +53,7 @@ describe('Single Selection', () => { { events: selCmpts['two'].events, update: - 'datum && item().mark.marktype !== \'group\' ? {unit: "", values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', + 'datum && item().mark.marktype !== \'group\' ? {unit: "", fields: two_tuple_fields, values: [[(item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon"], (item().isVoronoi ? datum.datum : datum)["bin_maxbins_10_Miles_per_Gallon_end"]], (item().isVoronoi ? datum.datum : datum)["Origin"]]} : null', force: true } ] From ddbe1b7fa9214b3b69eb43b898ccfec55e5f4704 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 15:13:29 +0530 Subject: [PATCH 08/14] Update inputs selection transform to new tuple structure. --- src/compile/selection/transforms/inputs.ts | 6 +++--- test/compile/selection/inputs.test.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compile/selection/transforms/inputs.ts b/src/compile/selection/transforms/inputs.ts index 4fc39aeb64..57323e64f9 100644 --- a/src/compile/selection/transforms/inputs.ts +++ b/src/compile/selection/transforms/inputs.ts @@ -1,7 +1,7 @@ -import {stringValue} from 'vega-util'; import {accessPathWithDatum, varName} from '../../../util'; import {TUPLE} from '../selection'; import nearest from './nearest'; +import {TUPLE_FIELDS} from './project'; import {TransformCompiler} from './transforms'; const inputBindings: TransformCompiler = { @@ -40,11 +40,11 @@ const inputBindings: TransformCompiler = { const name = selCmpt.name; const proj = selCmpt.project; const signal = signals.filter(s => s.name === name + TUPLE)[0]; - const fields = proj.map(p => stringValue(p.field)).join(', '); + const fields = name + TUPLE + TUPLE_FIELDS; const values = proj.map(p => varName(`${name}_${p.field}`)); if (values.length) { - signal.update = `${values.join(' && ')} ? {fields: [${fields}], values: [${values.join(', ')}]} : null`; + signal.update = `${values.join(' && ')} ? {fields: ${fields}, values: [${values.join(', ')}]} : null`; } delete signal.value; diff --git a/test/compile/selection/inputs.test.ts b/test/compile/selection/inputs.test.ts index 2c457ec4b6..cf51b41992 100644 --- a/test/compile/selection/inputs.test.ts +++ b/test/compile/selection/inputs.test.ts @@ -58,7 +58,7 @@ describe('Inputs Selection Transform', () => { assert.includeDeepMembers(selection.assembleUnitSelectionSignals(model, []), [ { name: 'one_tuple', - update: 'one__vgsid_ ? {fields: ["_vgsid_"], values: [one__vgsid_]} : null' + update: 'one__vgsid_ ? {fields: one_tuple_fields, values: [one__vgsid_]} : null' } ]); @@ -83,7 +83,7 @@ describe('Inputs Selection Transform', () => { { name: 'two_tuple', update: - 'two_Cylinders && two_Horsepower ? {fields: ["Cylinders", "Horsepower"], values: [two_Cylinders, two_Horsepower]} : null' + 'two_Cylinders && two_Horsepower ? {fields: two_tuple_fields, values: [two_Cylinders, two_Horsepower]} : null' } ]); @@ -119,7 +119,7 @@ describe('Inputs Selection Transform', () => { { name: 'three_tuple', update: - 'three_Cylinders && three_Origin ? {fields: ["Cylinders", "Origin"], values: [three_Cylinders, three_Origin]} : null' + 'three_Cylinders && three_Origin ? {fields: three_tuple_fields, values: [three_Cylinders, three_Origin]} : null' } ]); From 98a2b12b0b80d5d81a71daff9f37a4175e1f08b7 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 19:26:00 +0530 Subject: [PATCH 09/14] Add a top-level signal for reading a selection's resolved values. --- src/compile/selection/selection.ts | 20 ++++++++--- src/compile/selection/single.ts | 16 +-------- src/compile/selection/transforms/project.ts | 6 ++-- test/compile/selection/single.test.ts | 37 ++++++++------------- 4 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index fee8c3c04a..57921e552b 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -29,7 +29,7 @@ export interface SelectionComponent { type: SelectionType; events: VgEventStream; // predicate?: string; - bind?: 'scales' | VgBinding | {[key: string]: VgBinding}; + bind?: 'scales' | VgBinding | Dict; resolve: SelectionResolution; empty: 'all' | 'none'; mark?: BrushConfig; @@ -163,8 +163,20 @@ export function assembleFacetSignals(model: FacetModel, signals: any[]) { } export function assembleTopLevelSignals(model: UnitModel, signals: any[]) { - let needsUnit = false; + let hasSelections = false; forEachSelection(model, (selCmpt, selCompiler) => { + const name = selCmpt.name; + const store = stringValue(name + STORE); + const hasSg = signals.filter(s => s.name === name); + if (!hasSg.length) { + signals.push({ + name: selCmpt.name, + update: `vlSelectionResolve(${store}` + + (selCmpt.resolve === 'global' ? ')' : `, ${stringValue(selCmpt.resolve)})`) + }); + } + hasSelections = true; + if (selCompiler.topLevelSignals) { signals = selCompiler.topLevelSignals(model, selCmpt, signals); } @@ -174,11 +186,9 @@ export function assembleTopLevelSignals(model: UnitModel, signals: any[]) { signals = txCompiler.topLevelSignals(model, selCmpt, signals); } }); - - needsUnit = true; }); - if (needsUnit) { + if (hasSelections) { const hasUnit = signals.filter(s => s.name === 'unit'); if (!hasUnit.length) { signals.unshift({ diff --git a/src/compile/selection/single.ts b/src/compile/selection/single.ts index 062ad7b22d..3ed6647cbe 100644 --- a/src/compile/selection/single.ts +++ b/src/compile/selection/single.ts @@ -1,25 +1,11 @@ -import {stringValue} from 'vega-util'; - import {signals as multiSignals} from './multi'; -import {SelectionCompiler, STORE, TUPLE, unitName} from './selection'; +import {SelectionCompiler, TUPLE, unitName} from './selection'; const single: SelectionCompiler = { scaleDomain: 'vlSingleDomain', signals: multiSignals, - topLevelSignals: (model, selCmpt, signals) => { - const hasSignal = signals.filter(s => s.name === selCmpt.name); - const data = `data(${stringValue(selCmpt.name + STORE)})`; - const values = `${data}[0].values`; - return hasSignal.length - ? signals - : signals.concat({ - name: selCmpt.name, - update: `${data}.length && {` + selCmpt.project.map((p, i) => `${p.field}: ${values}[${i}]`).join(', ') + '}' - }); - }, - modifyExpr: (model, selCmpt) => { const tpl = selCmpt.name + TUPLE; return tpl + ', ' + (selCmpt.resolve === 'global' ? 'true' : `{unit: ${unitName(model)}}`); diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index 17f5214745..5c85babf30 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -2,7 +2,7 @@ import {ScaleChannel, SingleDefChannel} from '../../../channel'; import * as log from '../../../log'; import {hasContinuousDomain, isBinScale} from '../../../scale'; import {SelectionDef} from '../../../selection'; -import {keys} from '../../../util'; +import {Dict, keys} from '../../../util'; import {TimeUnitComponent, TimeUnitNode} from '../../data/timeunit'; import {ProjectSelectionComponent, SelectionComponent, TUPLE, TupleStoreType} from '../selection'; import {TransformCompiler} from './transforms'; @@ -16,8 +16,8 @@ const project: TransformCompiler = { }, parse: (model, selDef, selCmpt) => { - const timeUnits: {[field: string]: TimeUnitComponent} = {}; - const f: {[field: string]: ProjectSelectionComponent} = {}; + const timeUnits: Dict = {}; + const f: Dict = {}; const p = selCmpt.project || (selCmpt.project = []); selCmpt.fields = {}; diff --git a/test/compile/selection/single.test.ts b/test/compile/selection/single.test.ts index 644864b62e..315eae7e9d 100644 --- a/test/compile/selection/single.test.ts +++ b/test/compile/selection/single.test.ts @@ -23,7 +23,8 @@ describe('Single Selection', () => { type: 'single', nearest: true, on: 'mouseover', - encodings: ['y', 'color'] + encodings: ['y', 'color'], + resolve: "intersect" } })); @@ -69,7 +70,7 @@ describe('Single Selection', () => { assert.equal(oneExpr, 'one_tuple, true'); const twoExpr = single.modifyExpr(model, selCmpts['two']); - assert.equal(twoExpr, 'two_tuple, true'); + assert.equal(twoExpr, 'two_tuple, {unit: ""}'); const signals = selection.assembleUnitSelectionSignals(model, []); assert.includeDeepMembers(signals, [ @@ -95,34 +96,22 @@ describe('Single Selection', () => { }); it('builds top-level signals', () => { - const oneSg = single.topLevelSignals(model, selCmpts['one'], []); - assert.sameDeepMembers(oneSg, [ + const signals = selection.assembleTopLevelSignals(model, []); + assert.includeDeepMembers(signals, [ { name: 'one', - update: 'data("one_store").length && {_vgsid_: data("one_store")[0].values[0]}' - } - ]); - - const twoSg = single.topLevelSignals(model, selCmpts['two'], []); - assert.sameDeepMembers(twoSg, [ + update: 'vlSelectionResolve("one_store")' + }, { name: 'two', - update: - 'data("two_store").length && {Miles_per_Gallon: data("two_store")[0].values[0], Origin: data("two_store")[0].values[1]}' + update: 'vlSelectionResolve("two_store", "intersect")' + }, + { + name: 'unit', + value: {}, + on: [{events: 'mousemove', update: 'isTuple(group()) ? group() : unit'}] } ]); - - const signals = selection.assembleTopLevelSignals(model, []); - assert.includeDeepMembers( - signals, - [ - { - name: 'unit', - value: {}, - on: [{events: 'mousemove', update: 'isTuple(group()) ? group() : unit'}] - } - ].concat(oneSg, twoSg) - ); }); it('builds unit datasets', () => { From 605f1cf63db65a3cf8a8907c50612343de93ce24 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sat, 21 Jul 2018 19:38:35 +0530 Subject: [PATCH 10/14] Update scale bindings to use the new top-level selection signal. With scale bindings, the top-level signal needs to be assembled from the constituent top-level channelSignals which contain the correct state of the selection (i.e., the unit selection most recently interacted with). This commit also broadens test coverage of selection-scale bindings. --- src/compile/selection/interval.ts | 2 - src/compile/selection/multi.ts | 2 - src/compile/selection/selection.ts | 38 ++- src/compile/selection/single.ts | 2 - src/compile/selection/transforms/scales.ts | 50 +++- test/compile/selection/scales.test.ts | 317 ++++++++++++++------- 6 files changed, 271 insertions(+), 140 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index 4ea464b343..46443f6953 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -21,8 +21,6 @@ export const BRUSH = '_brush'; export const SCALE_TRIGGER = '_scale_trigger'; const interval: SelectionCompiler = { - scaleDomain: 'vlIntervalDomain', - signals: (model, selCmpt) => { const name = selCmpt.name; const fieldsSg = name + TUPLE + TUPLE_FIELDS; diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index a5b03a3090..e53564d617 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -42,8 +42,6 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { } const multi: SelectionCompiler = { - scaleDomain: 'vlMultiDomain', - signals: signals, modifyExpr: (model, selCmpt) => { diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index 57921e552b..4e94f099cb 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -23,6 +23,7 @@ export const STORE = '_store'; export const TUPLE = '_tuple'; export const MODIFY = '_modify'; export const SELECTION_DOMAIN = '_selection_domain_'; +export const VL_SELECTION_RESOLVE = 'vlSelectionResolve'; export interface SelectionComponent { name: string; @@ -62,7 +63,6 @@ export interface SelectionCompiler { topLevelSignals?: (model: Model, selCmpt: SelectionComponent, signals: any[]) => any[]; modifyExpr: (model: UnitModel, selCmpt: SelectionComponent) => string; marks?: (model: UnitModel, selCmpt: SelectionComponent, marks: any[]) => any[]; - scaleDomain: string; // Vega expr string to materialize a scale domain. } export function parseUnitSelection(model: UnitModel, selDefs: Dict) { @@ -171,7 +171,8 @@ export function assembleTopLevelSignals(model: UnitModel, signals: any[]) { if (!hasSg.length) { signals.push({ name: selCmpt.name, - update: `vlSelectionResolve(${store}` + + update: + `${VL_SELECTION_RESOLVE}(${store}` + (selCmpt.resolve === 'global' ? ')' : `, ${stringValue(selCmpt.resolve)})`) }); } @@ -257,8 +258,8 @@ export function selectionPredicate(model: Model, selections: LogicalOperand 1) { warn( 'A "field" or "encoding" must be specified when using a selection as a scale domain. ' + - `Using "field": ${stringValue(selDomain.field)}.` + `Using "field": ${stringValue(field)}.` ); } + } else if (encoding && !field) { + const encodings = selCmpt.project.filter(p => p.channel === encoding); + if (!encodings.length || encodings.length > 1) { + field = selCmpt.project[0].field; + warn( + (!encodings.length ? 'No ' : 'Multiple ') + + `matching ${stringValue(encoding)} encoding found for selection ${stringValue(selDomain.selection)}. ` + + `Using "field": ${stringValue(field)}.` + ); + } else { + field = encodings[0].field; + } } - return { - signal: - compiler(selCmpt.type).scaleDomain + - `(${stringValue(name + STORE)}, ${stringValue(selDomain.encoding || null)}, ` + - stringValue(selDomain.field || null) + - (selCmpt.resolve === 'global' ? ')' : `, ${stringValue(selCmpt.resolve)})`) - }; + + return {signal: accessPathWithDatum(field, name)}; } return {signal: 'null'}; diff --git a/src/compile/selection/single.ts b/src/compile/selection/single.ts index 3ed6647cbe..51885bd77e 100644 --- a/src/compile/selection/single.ts +++ b/src/compile/selection/single.ts @@ -2,8 +2,6 @@ import {signals as multiSignals} from './multi'; import {SelectionCompiler, TUPLE, unitName} from './selection'; const single: SelectionCompiler = { - scaleDomain: 'vlSingleDomain', - signals: multiSignals, modifyExpr: (model, selCmpt) => { diff --git a/src/compile/selection/transforms/scales.ts b/src/compile/selection/transforms/scales.ts index a496e93305..d83b9fb8e9 100644 --- a/src/compile/selection/transforms/scales.ts +++ b/src/compile/selection/transforms/scales.ts @@ -2,8 +2,9 @@ import {stringValue} from 'vega-util'; import {Channel, ScaleChannel, X, Y} from '../../../channel'; import * as log from '../../../log'; import {hasContinuousDomain, isBinScale} from '../../../scale'; +import {accessPathWithDatum, varName} from '../../../util'; import {UnitModel} from '../../unit'; -import {channelSignalName} from '../selection'; +import {channelSignalName, VL_SELECTION_RESOLVE} from '../selection'; import {TransformCompiler} from './transforms'; const scaleBindings: TransformCompiler = { @@ -12,6 +13,7 @@ const scaleBindings: TransformCompiler = { }, parse: (model, selDef, selCmpt) => { + const name = varName(selCmpt.name); const bound: Channel[] = (selCmpt.scales = []); selCmpt.project.forEach(p => { @@ -24,36 +26,56 @@ const scaleBindings: TransformCompiler = { return; } - scale.set('domainRaw', {signal: channelSignalName(selCmpt, channel, 'data')}, true); + scale.set('domainRaw', {signal: accessPathWithDatum(p.field, name)}, true); bound.push(channel); // Bind both x/y for diag plot of repeated views. if (model.repeater && model.repeater.row === model.repeater.column) { const scale2 = model.getScaleComponent(channel === X ? Y : X); - scale2.set('domainRaw', {signal: channelSignalName(selCmpt, channel, 'data')}, true); + scale2.set('domainRaw', {signal: accessPathWithDatum(p.field, name)}, true); } }); }, topLevelSignals: (model, selCmpt, signals) => { - // Top-level signals are only needed when coordinating composed views. - if (!model.parent) { + const channelSignals = selCmpt.scales + .filter(channel => { + return !signals.filter(s => s.name === channelSignalName(selCmpt, channel, 'data')).length; + }) + .map(channel => { + return {channel, signal: channelSignalName(selCmpt, channel, 'data')}; + }); + + // Top-level signals are only needed for multiview displays and if this + // view's top-level signals haven't already been generated. + if (!model.parent || !channelSignals.length) { return signals; } - const channels = selCmpt.scales.filter(channel => { - return !signals.filter(s => s.name === channelSignalName(selCmpt, channel, 'data')).length; - }); + // vlSelectionResolve does not account for the behavior of bound scales in + // multiview displays. Each unit view adds a tuple to the store, but the + // state of the selection is the unit selection most recently updated. This + // state is captured by the top-level signals that we insert and "push + // outer" to from within the units. We need to reassemble this state into + // the top-level named signal, except no single selCmpt has a global view. + const namedSg = signals.filter(s => s.name === selCmpt.name)[0]; + const update = namedSg.update; + if (update.indexOf(VL_SELECTION_RESOLVE) >= 0) { + namedSg.update = '{' + channelSignals.map(cs => `${selCmpt.fields[cs.channel]}: ${cs.signal}`).join(', ') + '}'; + } else { + for (const cs of channelSignals) { + const mapping = `, ${selCmpt.fields[cs.channel]}: ${cs.signal}`; + if (update.indexOf(mapping) < 0) { + namedSg.update = update.substring(0, update.length - 1) + mapping + '}'; + } + } + } - return signals.concat( - channels.map(channel => { - return {name: channelSignalName(selCmpt, channel, 'data')}; - }) - ); + return signals.concat(channelSignals.map(cs => ({name: cs.signal}))); }, signals: (model, selCmpt, signals) => { - // Nested signals need only push to top-level signals when within composed views. + // Nested signals need only push to top-level signals with multiview displays. if (model.parent) { selCmpt.scales.forEach(channel => { const signal = signals.filter(s => s.name === channelSignalName(selCmpt, channel, 'data'))[0]; diff --git a/test/compile/selection/scales.test.ts b/test/compile/selection/scales.test.ts index 63f8227807..945249271a 100644 --- a/test/compile/selection/scales.test.ts +++ b/test/compile/selection/scales.test.ts @@ -1,89 +1,169 @@ /* tslint:disable:quotemark */ import {assert} from 'chai'; +import {X} from '../../../src/channel'; import {assembleScalesForModel} from '../../../src/compile/scale/assemble'; +import {assembleTopLevelSignals, assembleUnitSelectionSignals} from '../../../src/compile/selection/selection'; +import {UnitModel} from '../../../src/compile/unit'; +import * as log from '../../../src/log'; import {Domain} from '../../../src/scale'; -import {parseConcatModel, parseRepeatModel} from '../../util'; +import {parseConcatModel, parseRepeatModel, parseUnitModelWithScale} from '../../util'; describe('Selection + Scales', () => { - it('assembles domainRaw from selection parameter', () => { - const model = parseConcatModel({ - vconcat: [ - { - mark: 'area', - selection: { - brush: {type: 'interval', encodings: ['x']}, - brush2: {type: 'multi', fields: ['price'], resolve: 'intersect'} + describe('domainRaw', () => { + it('is assembled from selection parameter', () => { + const model = parseConcatModel({ + vconcat: [ + { + mark: 'area', + selection: { + brush: {type: 'interval', encodings: ['x']}, + brush2: {type: 'multi', fields: ['price'], resolve: 'intersect'} + }, + encoding: { + x: {field: 'date', type: 'temporal'}, + y: {field: 'price', type: 'quantitative'} + } }, - encoding: { - x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} + { + selection: { + brush3: {type: 'interval'} + }, + mark: 'area', + encoding: { + x: { + field: 'date', + type: 'temporal', + scale: {domain: {selection: 'brush', encoding: 'x'}} + }, + y: { + field: 'price', + type: 'quantitative', + scale: {domain: {selection: 'brush2', field: 'price'}} + }, + color: { + field: 'symbol', + type: 'nominal', + scale: {domain: {selection: 'brush2'} as Domain} + }, + opacity: { + field: 'symbol', + type: 'nominal', + scale: {domain: {selection: 'brush3'} as Domain} + } + } + } + ], + resolve: { + scale: { + color: 'independent', + opacity: 'independent' } + } + }); + + model.parseScale(); + model.parseSelection(); + + const scales = assembleScalesForModel(model.children[1]); + const xscale = scales[0]; + const yscale = scales[1]; + const cscale = scales[2]; + const oscale = scales[3]; + + assert.isObject(xscale.domain); + assert.property(xscale, 'domainRaw'); + assert.propertyVal(xscale.domainRaw, 'signal', 'brush["date"]'); + + assert.isObject(yscale.domain); + assert.property(yscale, 'domainRaw'); + assert.deepPropertyVal(yscale.domainRaw, 'signal', 'brush2["price"]'); + + assert.isObject(cscale.domain); + assert.property(cscale, 'domainRaw'); + assert.propertyVal(cscale.domainRaw, 'signal', 'brush2["price"]'); + + assert.isObject(oscale.domain); + assert.property(oscale, 'domainRaw'); + assert.propertyVal(oscale.domainRaw, 'signal', 'null'); + }); + + it('should bind both scales in diagonal repeated views', () => { + const model = parseRepeatModel({ + repeat: { + row: ['Horsepower', 'Acceleration'], + column: ['Miles_per_Gallon', 'Acceleration'] }, - { + spec: { + data: {url: 'data/cars.json'}, + mark: 'point', selection: { - brush3: {type: 'interval'} + grid: { + type: 'interval', + resolve: 'global', + bind: 'scales' + } }, - mark: 'area', encoding: { - x: { - field: 'date', - type: 'temporal', - scale: {domain: {selection: 'brush', encoding: 'x'}} - }, - y: { - field: 'price', - type: 'quantitative', - scale: {domain: {selection: 'brush2', field: 'price'}} - }, - color: { - field: 'symbol', - type: 'nominal', - scale: {domain: {selection: 'brush2'} as Domain} - }, - opacity: { - field: 'symbol', - type: 'nominal', - scale: {domain: {selection: 'brush3'} as Domain} - } + x: {field: {repeat: 'column'}, type: 'quantitative'}, + y: {field: {repeat: 'row'}, type: 'quantitative'}, + color: {field: 'Origin', type: 'nominal'} } } - ], - resolve: { - scale: { - color: 'independent', - opacity: 'independent' - } - } - }); - - model.parseScale(); - model.parseSelection(); + }); - const scales = assembleScalesForModel(model.children[1]); - const xscale = scales[0]; - const yscale = scales[1]; - const cscale = scales[2]; - const oscale = scales[3]; + model.parseScale(); + model.parseSelection(); - assert.isObject(xscale.domain); - assert.property(xscale, 'domainRaw'); - assert.propertyVal(xscale.domainRaw, 'signal', 'vlIntervalDomain("brush_store", "x", null)'); - - assert.isObject(yscale.domain); - assert.property(yscale, 'domainRaw'); - assert.deepPropertyVal(yscale.domainRaw, 'signal', 'vlMultiDomain("brush2_store", null, "price", "intersect")'); + const scales = assembleScalesForModel(model.children[3]); + assert.isTrue(scales.length === 2); + assert.property(scales[0], 'domainRaw'); + assert.property(scales[1], 'domainRaw'); + assert.propertyVal(scales[0].domainRaw, 'signal', 'grid["Acceleration"]'); + assert.propertyVal(scales[1].domainRaw, 'signal', 'grid["Acceleration"]'); + }); - assert.isObject(cscale.domain); - assert.property(cscale, 'domainRaw'); - assert.propertyVal(cscale.domainRaw, 'signal', 'vlMultiDomain("brush2_store", null, "price", "intersect")'); + it('should be merged for layered views', () => { + const model = parseConcatModel({ + data: {url: 'data/sp500.csv'}, + vconcat: [ + { + layer: [ + { + mark: 'point', + encoding: { + x: { + field: 'date', + type: 'temporal', + scale: {domain: {selection: 'brush'}} + }, + y: {field: 'price', type: 'quantitative'} + } + } + ] + }, + { + mark: 'area', + selection: { + brush: {type: 'interval', encodings: ['x']} + }, + encoding: { + x: {field: 'date', type: 'temporal'}, + y: {field: 'price', type: 'quantitative'} + } + } + ] + }); - assert.isObject(oscale.domain); - assert.property(oscale, 'domainRaw'); - assert.propertyVal(oscale.domainRaw, 'signal', 'null'); + model.parseScale(); + model.parseSelection(); + const scales = assembleScalesForModel(model.children[0]); + assert.property(scales[0], 'domainRaw'); + assert.propertyVal(scales[0].domainRaw, 'signal', 'brush["date"]'); + }); }); - it('should bind both scales in diagonal repeated views', () => { + describe('signals', () => { const model = parseRepeatModel({ repeat: { row: ['Horsepower', 'Acceleration'], @@ -110,50 +190,75 @@ describe('Selection + Scales', () => { model.parseScale(); model.parseSelection(); - const scales = assembleScalesForModel(model.children[3]); - assert.isTrue(scales.length === 2); - assert.property(scales[0], 'domainRaw'); - assert.property(scales[1], 'domainRaw'); - assert.propertyVal(scales[0].domainRaw, 'signal', 'grid_Acceleration'); - assert.propertyVal(scales[1].domainRaw, 'signal', 'grid_Acceleration'); + it('should be marked as push: outer', () => { + const signals = assembleUnitSelectionSignals(model.children[0] as UnitModel, []); + const hp = signals.filter(s => s.name === 'grid_Horsepower'); + const mpg = signals.filter(s => s.name === 'grid_Miles_per_Gallon'); + + assert.lengthOf(hp, 1); + assert.propertyVal(hp[0], 'push', 'outer'); + assert.notProperty(hp[0], 'value'); + assert.notProperty(hp[0], 'update'); + + assert.lengthOf(mpg, 1); + assert.propertyVal(mpg[0], 'push', 'outer'); + assert.notProperty(mpg[0], 'value'); + assert.notProperty(mpg[0], 'update'); + }); + + it('should be assembled at the top-level', () => { + const signals = assembleTopLevelSignals(model.children[0] as UnitModel, []); + const hp = signals.filter(s => s.name === 'grid_Horsepower'); + const mpg = signals.filter(s => s.name === 'grid_Miles_per_Gallon'); + let named = signals.filter(s => s.name === 'grid'); + + assert.lengthOf(hp, 1); + assert.lengthOf(mpg, 1); + assert.lengthOf(named, 1); + assert.equal(named[0].update, '{Miles_per_Gallon: grid_Miles_per_Gallon, Horsepower: grid_Horsepower}'); + + const signals2 = assembleTopLevelSignals(model.children[1] as UnitModel, signals); + const acc = signals2.filter(s => s.name === 'grid_Acceleration'); + named = signals2.filter(s => s.name === 'grid'); + + assert.lengthOf(acc, 1); + assert.lengthOf(named, 1); + assert.equal( + named[0].update, + '{Miles_per_Gallon: grid_Miles_per_Gallon, Horsepower: grid_Horsepower, Acceleration: grid_Acceleration}' + ); + }); }); - it('should merge domainRaw for layered views', () => { - const model = parseConcatModel({ - data: {url: 'data/sp500.csv'}, - vconcat: [ - { - layer: [ - { - mark: 'point', - encoding: { - x: { - field: 'date', - type: 'temporal', - scale: {domain: {selection: 'brush'}} - }, - y: {field: 'price', type: 'quantitative'} - } - } - ] + it( + 'should not bind for unavailable/unsupported scales', + log.wrap(localLogger => { + let model = parseUnitModelWithScale({ + data: {url: 'data/cars.json'}, + selection: { + grid: {type: 'interval', bind: 'scales'} }, - { - mark: 'area', - selection: { - brush: {type: 'interval', encodings: ['x']} - }, - encoding: { - x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} - } + mark: 'circle', + encoding: { + y: {field: 'Miles_per_Gallon', type: 'quantitative'} } - ] - }); + }); + model.parseSelection(); + assert.equal(localLogger.warns[0], log.message.cannotProjectOnChannelWithoutField(X)); - model.parseScale(); - model.parseSelection(); - const scales = assembleScalesForModel(model.children[0]); - assert.property(scales[0], 'domainRaw'); - assert.propertyVal(scales[0].domainRaw, 'signal', 'vlIntervalDomain("brush_store", null, "date")'); - }); + model = parseUnitModelWithScale({ + data: {url: 'data/cars.json'}, + selection: { + grid: {type: 'interval', bind: 'scales'} + }, + mark: 'circle', + encoding: { + x: {field: 'Origin', type: 'nominal'}, + y: {field: 'Miles_per_Gallon', type: 'quantitative'} + } + }); + model.parseSelection(); + assert.equal(localLogger.warns[1], log.message.SCALE_BINDINGS_CONTINUOUS); + }) + ); }); From ea88efbeaf709b998a0095fea33a64d99f6dbdb7 Mon Sep 17 00:00:00 2001 From: Arvind Satyanarayan Date: Sun, 19 Aug 2018 13:55:48 -0400 Subject: [PATCH 11/14] Update runtime tests to new store structure. --- src/util.ts | 8 ++++ test-runtime/discrete.test.ts | 21 +++++++---- test-runtime/interval.test.ts | 68 +++++++++++++++++++++------------- test-runtime/translate.test.ts | 38 +++++++++---------- test-runtime/util.ts | 68 +++++++++++++++++----------------- test-runtime/zoom.test.ts | 24 ++++++------ 6 files changed, 130 insertions(+), 97 deletions(-) diff --git a/src/util.ts b/src/util.ts index aa8e21d3ec..7490ab11fe 100644 --- a/src/util.ts +++ b/src/util.ts @@ -110,6 +110,14 @@ export function flatten(arrays: any[]) { return [].concat.apply([], arrays); } +export function fill(val: T, len: number) { + const arr: T[] = []; + for (let i = 0; i < len; ++i) { + arr.push(val); + } + return arr; +} + /** * recursively merges src into dest */ diff --git a/test-runtime/discrete.test.ts b/test-runtime/discrete.test.ts index 63255e785e..483a98fc62 100644 --- a/test-runtime/discrete.test.ts +++ b/test-runtime/discrete.test.ts @@ -1,4 +1,6 @@ import {assert} from 'chai'; +import {SELECTION_ID} from '../src/selection'; +import {fill} from '../src/util'; import {embedFn, hits as hitsMaster, pt, spec, testRenderFn} from './util'; ['single', 'multi'].forEach(type => { @@ -12,9 +14,10 @@ import {embedFn, hits as hitsMaster, pt, spec, testRenderFn} from './util'; embed(spec('unit', i, {type})); const store = browser.execute(pt('qq', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].encodings, 0); assert.lengthOf(store[0].fields, 1); assert.lengthOf(store[0].values, 1); + assert.equal(store[0].fields[0].field, SELECTION_ID); + assert.equal(store[0].fields[0].type, 'E'); testRender(`click_${i}`); } }); @@ -28,8 +31,10 @@ import {embedFn, hits as hitsMaster, pt, spec, testRenderFn} from './util'; emb(i); const store = browser.execute(pt('qq', i)).value; assert.lengthOf(store, 1); - assert.deepEqual(store[0].encodings, encodings); - assert.deepEqual(store[0].fields, fields); + assert.lengthOf(store[0].fields, fields.length); + assert.lengthOf(store[0].values, fields.length); + assert.deepEqual(store[0].fields.map((f: any) => f.field), fields); + assert.deepEqual(store[0].fields.map((f: any) => f.type), fill('E', fields.length)); assert.deepEqual(store[0].values, values[i]); testRender(`${encodings}_${fields}_${i}`); } @@ -61,18 +66,18 @@ import {embedFn, hits as hitsMaster, pt, spec, testRenderFn} from './util'; it('should support selecting bins', () => { const encodings = ['x', 'color', 'y']; const fields = ['a', 'c', 'b']; + const types = ['R-RE', 'E', 'R-RE']; const values = [[[1, 2], 0, [40, 50]], [[8, 9], 1, [10, 20]]]; for (let i = 0; i < hits.bins.length; i++) { embed(spec('unit', i, {type, encodings}, {x: {bin: true}, y: {bin: true}})); const store = browser.execute(pt('bins', i)).value; assert.lengthOf(store, 1); - assert.sameMembers(store[0].encodings, encodings); - assert.sameMembers(store[0].fields, fields); + assert.lengthOf(store[0].fields, fields.length); + assert.lengthOf(store[0].values, fields.length); + assert.sameMembers(store[0].fields.map((f: any) => f.field), fields); + assert.sameMembers(store[0].fields.map((f: any) => f.type), types); assert.sameDeepMembers(store[0].values, values[i]); - assert.property(store[0], 'bin_a'); - assert.property(store[0], 'bin_b'); - assert.notProperty(store[0], 'bin_c'); testRender(`bins_${i}`); } }); diff --git a/test-runtime/interval.test.ts b/test-runtime/interval.test.ts index 7ac644be65..c67a5e2e6d 100644 --- a/test-runtime/interval.test.ts +++ b/test-runtime/interval.test.ts @@ -12,13 +12,16 @@ describe('interval selections at runtime in unit views', () => { embed(spec('unit', i, {type})); const store = browser.execute(brush('drag', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 2); - assert.equal(store[0].intervals[0].encoding, 'x'); - assert.equal(store[0].intervals[0].field, 'a'); - assert.equal(store[0].intervals[1].encoding, 'y'); - assert.equal(store[0].intervals[1].field, 'b'); - assert.lengthOf(store[0].intervals[0].extent, 2); - assert.lengthOf(store[0].intervals[1].extent, 2); + assert.lengthOf(store[0].fields, 2); + assert.lengthOf(store[0].values, 2); + assert.equal(store[0].fields[0].channel, 'x'); + assert.equal(store[0].fields[0].field, 'a'); + assert.equal(store[0].fields[0].type, 'R'); + assert.equal(store[0].fields[1].channel, 'y'); + assert.equal(store[0].fields[1].field, 'b'); + assert.equal(store[0].fields[1].type, 'R'); + assert.lengthOf(store[0].values[0], 2); + assert.lengthOf(store[0].values[1], 2); testRender(`drag_${i}`); } }); @@ -28,10 +31,12 @@ describe('interval selections at runtime in unit views', () => { for (let i = 0; i < hits.drag.length; i++) { const store = browser.execute(brush('drag', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 1); - assert.equal(store[0].intervals[0].encoding, 'x'); - assert.equal(store[0].intervals[0].field, 'a'); - assert.lengthOf(store[0].intervals[0].extent, 2); + assert.lengthOf(store[0].fields, 1); + assert.lengthOf(store[0].values, 1); + assert.equal(store[0].fields[0].channel, 'x'); + assert.equal(store[0].fields[0].field, 'a'); + assert.equal(store[0].fields[0].type, 'R'); + assert.lengthOf(store[0].values[0], 2); testRender(`x_${i}`); } @@ -39,10 +44,12 @@ describe('interval selections at runtime in unit views', () => { for (let i = 0; i < hits.drag.length; i++) { const store = browser.execute(brush('drag', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 1); - assert.equal(store[0].intervals[0].encoding, 'y'); - assert.equal(store[0].intervals[0].field, 'b'); - assert.lengthOf(store[0].intervals[0].extent, 2); + assert.lengthOf(store[0].fields, 1); + assert.lengthOf(store[0].values, 1); + assert.equal(store[0].fields[0].channel, 'y'); + assert.equal(store[0].fields[0].field, 'b'); + assert.equal(store[0].fields[0].type, 'R'); + assert.lengthOf(store[0].values[0], 2); testRender(`y_${i}`); } }); @@ -75,9 +82,12 @@ describe('interval selections at runtime in unit views', () => { for (let i = 0; i < hits.bins.length; i++) { const store = browser.execute(brush('bins', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 1); - // length == 2 indicates a quantitative scale was inverted. - assert.lengthOf(store[0].intervals[0].extent, 2); + assert.lengthOf(store[0].fields, 1); + assert.lengthOf(store[0].values, 1); + assert.equal(store[0].fields[0].channel, 'y'); + assert.equal(store[0].fields[0].field, 'b'); + assert.equal(store[0].fields[0].type, 'R'); + assert.lengthOf(store[0].values[0], 2); testRender(`bins_${i}`); } @@ -96,9 +106,16 @@ describe('interval selections at runtime in unit views', () => { embed(spec('unit', i, {type}, {x: {type: 'ordinal'}, y: {type: 'nominal'}})); const store = browser.execute(brush('drag', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 2); - assert.sameMembers(store[0].intervals[0].extent, xextents[i]); - assert.sameMembers(store[0].intervals[1].extent, yextents[i]); + assert.lengthOf(store[0].fields, 2); + assert.lengthOf(store[0].values, 2); + assert.equal(store[0].fields[0].channel, 'x'); + assert.equal(store[0].fields[0].field, 'a'); + assert.equal(store[0].fields[0].type, 'E'); + assert.equal(store[0].fields[1].channel, 'y'); + assert.equal(store[0].fields[1].field, 'b'); + assert.equal(store[0].fields[1].type, 'E'); + assert.sameMembers(store[0].values[0], xextents[i]); + assert.sameMembers(store[0].values[1], yextents[i]); testRender(`ord_${i}`); } @@ -108,7 +125,7 @@ describe('interval selections at runtime in unit views', () => { it('should brush over temporal domains', () => { const values = tuples.map(d => ({...d, a: new Date(2017, d.a)})); - const toNumber = '[0].intervals[0].extent.map((d) => +d)'; + const toNumber = '[0].values[0].map((d) => +d)'; embed(spec('unit', 0, {type, encodings: ['x']}, {values, x: {type: 'temporal'}})); let extents = [[1485969714000, 1493634384000], [1496346498000, 1504364922000]]; @@ -149,9 +166,10 @@ describe('interval selections at runtime in unit views', () => { ); const store = browser.execute(brush('drag', i)).value; assert.lengthOf(store, 1); - assert.lengthOf(store[0].intervals, 2); - assert.lengthOf(store[0].intervals[0].extent, 2); - assert.lengthOf(store[0].intervals[1].extent, 2); + assert.lengthOf(store[0].fields, 2); + assert.lengthOf(store[0].values, 2); + assert.lengthOf(store[0].values[0], 2); + assert.lengthOf(store[0].values[1], 2); testRender(`logpow_${i}`); } }); diff --git a/test-runtime/translate.test.ts b/test-runtime/translate.test.ts index 4a8f2cd858..52df5bf0cd 100644 --- a/test-runtime/translate.test.ts +++ b/test-runtime/translate.test.ts @@ -37,10 +37,10 @@ import { const drag = browser.execute(brush('drag', i)).value[0]; testRender(`${i}-0`); const translate = browser.execute(brush('translate', i, null, bind === unbound)).value[0]; - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[0], drag.intervals[0].extent[0]); - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[1], drag.intervals[0].extent[1]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[0], drag.intervals[1].extent[0]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[1], drag.intervals[1].extent[1]); + assert[assertExtent[bind].x[i]](translate.values[0][0], drag.values[0][0]); + assert[assertExtent[bind].x[i]](translate.values[0][1], drag.values[0][1]); + assert[assertExtent[bind].y[i]](translate.values[1][0], drag.values[1][0]); + assert[assertExtent[bind].y[i]](translate.values[1][1], drag.values[1][1]); testRender(`${i}-1`); } }); @@ -62,15 +62,15 @@ import { const drag = browser.execute(brush('bins', i)).value[0]; testRender(`bins_${i}-0`); const translate = browser.execute(brush('bins_translate', i, null, bind === unbound)).value[0]; - assert[assertExtent[bind].y[i]](translate.intervals[0].extent[0], drag.intervals[0].extent[0]); - assert[assertExtent[bind].y[i]](translate.intervals[0].extent[1], drag.intervals[0].extent[1]); + assert[assertExtent[bind].y[i]](translate.values[0][0], drag.values[0][0]); + assert[assertExtent[bind].y[i]](translate.values[0][1], drag.values[0][1]); testRender(`bins_${i}-1`); } }); it('should work with temporal domains', () => { const values = tuples.map(d => ({...d, a: new Date(2017, d.a)})); - const toNumber = '[0].intervals[0].extent.map((d) => +d)'; + const toNumber = '[0].values[0].map((d) => +d)'; for (let i = 0; i < hits.translate.length; i++) { embed(spec('unit', i, {type, ...binding, encodings: ['x']}, {values, x: {type: 'temporal'}})); @@ -99,10 +99,10 @@ import { const drag = browser.execute(brush('drag', i)).value[0]; testRender(`logpow_${i}-0`); const translate = browser.execute(brush('translate', i, null, bind === unbound)).value[0]; - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[0], drag.intervals[0].extent[0]); - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[1], drag.intervals[0].extent[1]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[0], drag.intervals[1].extent[0]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[1], drag.intervals[1].extent[1]); + assert[assertExtent[bind].x[i]](translate.values[0][0], drag.values[0][0]); + assert[assertExtent[bind].x[i]](translate.values[0][1], drag.values[0][1]); + assert[assertExtent[bind].y[i]](translate.values[1][0], drag.values[1][0]); + assert[assertExtent[bind].y[i]](translate.values[1][1], drag.values[1][1]); testRender(`logpow_${i}-1`); } }); @@ -124,10 +124,10 @@ import { const drag = browser.execute(brush('drag', i)).value[0]; testRender(`ord_${i}-0`); const translate = browser.execute(brush('translate', i, null, true)).value[0]; - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[0], drag.intervals[0].extent[0]); - assert[assertExtent[bind].x[i]](translate.intervals[0].extent[1], drag.intervals[0].extent[1]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[0], drag.intervals[1].extent[0]); - assert[assertExtent[bind].y[i]](translate.intervals[1].extent[1], drag.intervals[1].extent[1]); + assert[assertExtent[bind].x[i]](translate.values[0][0], drag.values[0][0]); + assert[assertExtent[bind].x[i]](translate.values[0][1], drag.values[0][1]); + assert[assertExtent[bind].y[i]](translate.values[1][0], drag.values[1][0]); + assert[assertExtent[bind].y[i]](translate.values[1][1], drag.values[1][1]); testRender(`ord_${i}-1`); } }); @@ -150,10 +150,10 @@ import { const xscale = browser.execute('return view._runtime.scales.x.value.domain()').value; const yscale = browser.execute('return view._runtime.scales.y.value.domain()').value; const drag = browser.execute(brush(specType, i, parent)).value[0]; - assert[assertExtents[specType].x[i]](drag.intervals[0].extent[0], xscale[0], `iter: ${i}`); - assert[assertExtents[specType].x[i]](drag.intervals[0].extent[1], xscale[1], `iter: ${i}`); - assert[assertExtents[specType].y[i]](drag.intervals[1].extent[0], yscale[0], `iter: ${i}`); - assert[assertExtents[specType].y[i]](drag.intervals[1].extent[1], yscale[1], `iter: ${i}`); + assert[assertExtents[specType].x[i]](drag.values[0][0], xscale[0], `iter: ${i}`); + assert[assertExtents[specType].x[i]](drag.values[0][1], xscale[1], `iter: ${i}`); + assert[assertExtents[specType].y[i]](drag.values[1][0], yscale[0], `iter: ${i}`); + assert[assertExtents[specType].y[i]](drag.values[1][1], yscale[1], `iter: ${i}`); testRender(`${specType}_${i}`); } }); diff --git a/test-runtime/util.ts b/test-runtime/util.ts index 35682494ab..5b87542c9a 100644 --- a/test-runtime/util.ts +++ b/test-runtime/util.ts @@ -95,42 +95,44 @@ function base(iter: number, sel: any, opts: any = {}): NormalizedUnitSpec | Norm const selection = {sel}; const mark = 'circle'; - return iter % 2 === 0 - ? { - data, - selection, - mark, - encoding: { - x, - y, - size, - color: { - condition: {selection: 'sel', ...color}, - value: 'grey' - } + if (iter % 2 === 0) { + return { + data, + selection, + mark, + encoding: { + x, + y, + size, + color: { + condition: {selection: 'sel', ...color}, + value: 'grey' } } - : { - data, - layer: [ - { - selection, - mark, - encoding: { - x, - y, - size, - color, - opacity: {value: 0.25} - } - }, - { - transform: [{filter: {selection: 'sel'}}], - mark, - encoding: {x, y, size, color} + }; + } else { + return { + data, + layer: [ + { + selection, + mark, + encoding: { + x, + y, + size, + color, + opacity: {value: 0.25} } - ] - }; + }, + { + transform: [{filter: {selection: 'sel'}}], + mark, + encoding: {x, y, size, color} + } + ] + }; + } } export function spec(compose: ComposeType, iter: number, sel: any, opts: any = {}): TopLevelSpec { diff --git a/test-runtime/zoom.test.ts b/test-runtime/zoom.test.ts index 7de0bf70c6..beda1ff0f6 100644 --- a/test-runtime/zoom.test.ts +++ b/test-runtime/zoom.test.ts @@ -34,8 +34,8 @@ const cmp = (a: number, b: number) => a - b; if (bind === unbound) { const drag = browser.execute(brush(brushKey, idx, parent)).value[0]; - xold = drag.intervals[0].extent.sort(cmp); - yold = encodings.indexOf('y') >= 0 ? drag.intervals[encodings.indexOf('x') + 1].extent.sort(cmp) : null; + xold = drag.values[0].sort(cmp); + yold = encodings.indexOf('y') >= 0 ? drag.values[encodings.indexOf('x') + 1].sort(cmp) : null; } else { xold = JSON.parse(browser.execute('return JSON.stringify(view._runtime.scales.x.value.domain())').value); yold = browser.execute('return view._runtime.scales.y.value.domain()').value; @@ -51,8 +51,8 @@ const cmp = (a: number, b: number) => a - b; testRender(`${inOut}-0`); const zoomed = browser.execute(zoom('zoom', i, inOut, null, bind === unbound)).value[0]; - const xnew = zoomed.intervals[0].extent.sort(cmp); - const ynew = zoomed.intervals[1].extent.sort(cmp); + const xnew = zoomed.values[0].sort(cmp); + const ynew = zoomed.values[1].sort(cmp); testRender(`${inOut}-1`); assert[assertExtent[inOut][0]](xnew[0], xold[0]); assert[assertExtent[inOut][1]](xnew[1], xold[1]); @@ -81,7 +81,7 @@ const cmp = (a: number, b: number) => a - b; testRender(`bins_${inOut}-0`); const zoomed = browser.execute(zoom('bins', i, inOut, null, bind === unbound)).value[0]; - const ynew = zoomed.intervals[0].extent.sort(cmp); + const ynew = zoomed.values[0].sort(cmp); assert[assertExtent[inOut][0]](ynew[0], yold[0]); assert[assertExtent[inOut][1]](ynew[1], yold[1]); testRender(`bins_${inOut}-1`); @@ -98,7 +98,7 @@ const cmp = (a: number, b: number) => a - b; testRender(`temporal_${inOut}-0`); const zoomed = browser.execute(zoom('zoom', i, inOut, null, bind === unbound)).value[0]; - const xnew = zoomed.intervals[0].extent.sort(cmp); + const xnew = zoomed.values[0].sort(cmp); assert[assertExtent[inOut][0]](+xnew[0], +new Date(xold[0])); assert[assertExtent[inOut][1]](+xnew[1], +new Date(xold[1])); testRender(`temporal_${inOut}-1`); @@ -122,8 +122,8 @@ const cmp = (a: number, b: number) => a - b; testRender(`logpow_${inOut}-0`); const zoomed = browser.execute(zoom('zoom', i, inOut, null, bind === unbound)).value[0]; - const xnew = zoomed.intervals[0].extent.sort(cmp); - const ynew = zoomed.intervals[1].extent.sort(cmp); + const xnew = zoomed.values[0].sort(cmp); + const ynew = zoomed.values[1].sort(cmp); assert[assertExtent[inOut][0]](xnew[0], xold[0]); assert[assertExtent[inOut][1]](xnew[1], xold[1]); assert[assertExtent[inOut][0]](ynew[0], yold[0]); @@ -150,8 +150,8 @@ const cmp = (a: number, b: number) => a - b; testRender(`ord_${inOut}-0`); const zoomed = browser.execute(zoom('zoom', i, inOut, null, bind === unbound)).value[0]; - const xnew = zoomed.intervals[0].extent.sort(cmp); - const ynew = zoomed.intervals[1].extent.sort(cmp); + const xnew = zoomed.values[0].sort(cmp); + const ynew = zoomed.values[1].sort(cmp); if (inOut === 'in') { assert.isAtMost(xnew.length, xold.length); @@ -172,8 +172,8 @@ const cmp = (a: number, b: number) => a - b; const parent = parentSelector(specType, i); const {inOut, xold, yold} = setup(specType, i, ['x', 'y'], parent); const zoomed = browser.execute(zoom('bins', i, inOut, null, bind === unbound)).value[0]; - const xnew = zoomed.intervals[0].extent.sort(cmp); - const ynew = zoomed.intervals[1].extent.sort(cmp); + const xnew = zoomed.values[0].sort(cmp); + const ynew = zoomed.values[1].sort(cmp); assert[assertExtent[inOut][0]](xnew[0], xold[0]); assert[assertExtent[inOut][1]](xnew[1], xold[1]); assert[assertExtent[inOut][0]](ynew[0], yold[0]); From 366f8c99da5be8ae1ad30992eb921334fc14890f Mon Sep 17 00:00:00 2001 From: Dominik Moritz Date: Sat, 13 Oct 2018 17:12:40 +0200 Subject: [PATCH 12/14] Replace forEach with for, remove as, remove push.apply, add test, and initialize fill array (#4216) * Replace forEach with for, remove as, add tests and initialize fill array * Get rid of push.apply * Unused import * Replace more forEach with for..of. --- src/compile/selection/interval.ts | 2 +- src/compile/selection/selection.ts | 6 +++--- src/compile/selection/transforms/inputs.ts | 4 ++-- src/compile/selection/transforms/project.ts | 8 ++++---- src/compile/selection/transforms/scales.ts | 19 ++++++++++++------- src/util.ts | 4 ++-- test/util.test.ts | 10 +++++++++- 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index 46443f6953..aa6dd9fcde 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -53,7 +53,7 @@ const interval: SelectionCompiler = { const scaleType = model.getScaleComponent(channel).get('type'); const toNum = hasContinuousDomain(scaleType) ? '+' : ''; - signals.push.apply(signals, cs); + signals.push(...cs); dataSignals.push(dname); scaleTriggers.push({ diff --git a/src/compile/selection/selection.ts b/src/compile/selection/selection.ts index 4e94f099cb..04edc3d0ae 100644 --- a/src/compile/selection/selection.ts +++ b/src/compile/selection/selection.ts @@ -119,7 +119,7 @@ export function assembleUnitSelectionSignals(model: UnitModel, signals: any[]) { const name = selCmpt.name; let modifyExpr = selCompiler.modifyExpr(model, selCmpt); - signals.push.apply(signals, selCompiler.signals(model, selCmpt)); + signals.push(...selCompiler.signals(model, selCmpt)); forEachTransform(selCmpt, txCompiler => { if (txCompiler.signals) { @@ -228,11 +228,11 @@ export function assembleUnitSelectionMarks(model: UnitModel, marks: any[]): any[ } export function assembleLayerSelectionMarks(model: LayerModel, marks: any[]): any[] { - model.children.forEach(child => { + for (const child of model.children) { if (isUnitModel(child)) { marks = assembleUnitSelectionMarks(child, marks); } - }); + } return marks; } diff --git a/src/compile/selection/transforms/inputs.ts b/src/compile/selection/transforms/inputs.ts index 57323e64f9..183530118a 100644 --- a/src/compile/selection/transforms/inputs.ts +++ b/src/compile/selection/transforms/inputs.ts @@ -15,7 +15,7 @@ const inputBindings: TransformCompiler = { const bind = selCmpt.bind; const datum = nearest.has(selCmpt) ? '(item().isVoronoi ? datum.datum : datum)' : 'datum'; - proj.forEach(p => { + for (const p of proj) { const sgname = varName(`${name}_${p.field}`); const hasSignal = signals.filter(s => s.name === sgname); if (!hasSignal.length) { @@ -31,7 +31,7 @@ const inputBindings: TransformCompiler = { bind: bind[p.field] || bind[p.channel] || bind }); } - }); + } return signals; }, diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index 5c85babf30..e05c1f72d6 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -1,4 +1,4 @@ -import {ScaleChannel, SingleDefChannel} from '../../../channel'; +import {ScaleChannel} from '../../../channel'; import * as log from '../../../log'; import {hasContinuousDomain, isBinScale} from '../../../scale'; import {SelectionDef} from '../../../selection'; @@ -23,10 +23,10 @@ const project: TransformCompiler = { // TODO: find a possible channel mapping for these fields. if (selDef.fields) { - p.push.apply(p, selDef.fields.map(field => ({field, type: 'E'}))); + p.push(...selDef.fields.map(field => ({field, type: 'E'}))); } - (selDef.encodings || []).forEach((channel: SingleDefChannel) => { + for (const channel of selDef.encodings || []) { const fieldDef = model.fieldDef(channel); if (fieldDef) { let field = fieldDef.field; @@ -67,7 +67,7 @@ const project: TransformCompiler = { } else { log.warn(log.message.cannotProjectOnChannelWithoutField(channel)); } - }); + } if (keys(timeUnits).length) { selCmpt.timeUnit = new TimeUnitNode(null, timeUnits); diff --git a/src/compile/selection/transforms/scales.ts b/src/compile/selection/transforms/scales.ts index d83b9fb8e9..6c0bbfde4c 100644 --- a/src/compile/selection/transforms/scales.ts +++ b/src/compile/selection/transforms/scales.ts @@ -1,5 +1,5 @@ import {stringValue} from 'vega-util'; -import {Channel, ScaleChannel, X, Y} from '../../../channel'; +import {Channel, isScaleChannel, X, Y} from '../../../channel'; import * as log from '../../../log'; import {hasContinuousDomain, isBinScale} from '../../../scale'; import {accessPathWithDatum, varName} from '../../../util'; @@ -16,14 +16,19 @@ const scaleBindings: TransformCompiler = { const name = varName(selCmpt.name); const bound: Channel[] = (selCmpt.scales = []); - selCmpt.project.forEach(p => { - const channel = p.channel as ScaleChannel; + for (const p of selCmpt.project) { + const channel = p.channel; + + if (!isScaleChannel(channel)) { + continue; + } + const scale = model.getScaleComponent(channel); const scaleType = scale ? scale.get('type') : undefined; if (!scale || !hasContinuousDomain(scaleType) || isBinScale(scaleType)) { log.warn(log.message.SCALE_BINDINGS_CONTINUOUS); - return; + continue; } scale.set('domainRaw', {signal: accessPathWithDatum(p.field, name)}, true); @@ -34,7 +39,7 @@ const scaleBindings: TransformCompiler = { const scale2 = model.getScaleComponent(channel === X ? Y : X); scale2.set('domainRaw', {signal: accessPathWithDatum(p.field, name)}, true); } - }); + } }, topLevelSignals: (model, selCmpt, signals) => { @@ -77,13 +82,13 @@ const scaleBindings: TransformCompiler = { signals: (model, selCmpt, signals) => { // Nested signals need only push to top-level signals with multiview displays. if (model.parent) { - selCmpt.scales.forEach(channel => { + for (const channel of selCmpt.scales) { const signal = signals.filter(s => s.name === channelSignalName(selCmpt, channel, 'data'))[0]; signal.push = 'outer'; delete signal.value; delete signal.update; - }); + } } return signals; diff --git a/src/util.ts b/src/util.ts index 7490ab11fe..e8369a8dd3 100644 --- a/src/util.ts +++ b/src/util.ts @@ -111,9 +111,9 @@ export function flatten(arrays: any[]) { } export function fill(val: T, len: number) { - const arr: T[] = []; + const arr = new Array(len); for (let i = 0; i < len; ++i) { - arr.push(val); + arr[i] = val; } return arr; } diff --git a/test/util.test.ts b/test/util.test.ts index 413c276946..c0dbaef8fd 100644 --- a/test/util.test.ts +++ b/test/util.test.ts @@ -1,5 +1,5 @@ import {assert} from 'chai'; -import {entries, fieldIntersection, flatAccessWithDatum, prefixGenerator, unique, uniqueId} from '../src/util'; +import {entries, fieldIntersection, fill, flatAccessWithDatum, prefixGenerator, unique, uniqueId} from '../src/util'; import { accessPathDepth, @@ -202,4 +202,12 @@ describe('util', () => { expect(uniqueId() === uniqueId()).toBeFalsy(); }); }); + + describe('fill', () => { + it('should return array of right length and filled with the right values', () => { + const arr = fill(42, 5); + expect(arr).toHaveLength(5); + expect(arr).toEqual([42, 42, 42, 42, 42]); + }); + }); }); From 97772d527a78f8ac5c0d3b549c64b3911db0cb70 Mon Sep 17 00:00:00 2001 From: Travis CI Date: Sat, 13 Oct 2018 18:20:50 +0000 Subject: [PATCH 13/14] [Travis] Update examples (build: 19319) --- .../circle_bubble_health_income.vg.json | 11 +- .../compiled/concat_bar_layer_circle.vg.json | 15 +- .../compiled/interactive_area_brush.vg.json | 9 +- examples/compiled/interactive_brush.vg.json | 9 +- .../compiled/interactive_concat_layer.vg.json | 15 +- .../interactive_dashboard_europe_pop.vg.json | 27 +- .../interactive_layered_crossfilter.vg.json | 27 +- ...ctive_layered_crossfilter_discrete.vg.json | 27 +- .../interactive_multi_line_tooltip.vg.json | 18 +- .../interactive_overview_detail.vg.json | 13 +- .../compiled/interactive_paintbrush.vg.json | 12 +- .../interactive_paintbrush_color.vg.json | 12 +- ...teractive_paintbrush_color_nearest.vg.json | 12 +- .../interactive_paintbrush_interval.vg.json | 12 +- .../interactive_paintbrush_simple_all.vg.json | 12 +- ...interactive_paintbrush_simple_none.vg.json | 15 +- .../interactive_panzoom_splom.vg.json | 112 ++++--- ...interactive_panzoom_vconcat_shared.vg.json | 14 +- .../interactive_query_widgets.vg.json | 13 +- .../interactive_seattle_weather.vg.json | 24 +- examples/compiled/interactive_splom.svg | 2 +- examples/compiled/interactive_splom.vg.json | 302 +++++++++++------- .../interactive_stocks_nearest_index.vg.json | 13 +- examples/compiled/isotype_grid.vg.json | 9 +- .../compiled/selection_bind_cylyr.vg.json | 13 +- .../compiled/selection_bind_origin.vg.json | 11 +- .../compiled/selection_brush_timeunit.vg.json | 13 +- .../selection_composition_and.vg.json | 16 +- .../compiled/selection_composition_or.vg.json | 16 +- examples/compiled/selection_concat.vg.json | 23 +- examples/compiled/selection_filter.vg.json | 11 +- .../selection_filter_composition.vg.json | 11 +- examples/compiled/selection_insert.vg.json | 12 +- .../selection_interval_mark_style.vg.json | 14 +- .../selection_layer_bar_month.vg.json | 11 +- .../selection_multi_condition.vg.json | 21 +- .../selection_project_binned_interval.vg.json | 9 +- .../selection_project_interval.vg.json | 9 +- .../selection_project_interval_x.vg.json | 9 +- .../selection_project_interval_x_y.vg.json | 9 +- .../selection_project_interval_y.vg.json | 9 +- .../compiled/selection_project_multi.vg.json | 11 +- .../selection_project_multi_cylinders.vg.json | 11 +- ...ion_project_multi_cylinders_origin.vg.json | 13 +- .../selection_project_multi_origin.vg.json | 13 +- .../compiled/selection_project_single.vg.json | 15 +- ...selection_project_single_cylinders.vg.json | 15 +- ...on_project_single_cylinders_origin.vg.json | 17 +- .../selection_project_single_origin.vg.json | 17 +- .../selection_resolution_global.vg.json | 189 ++++++----- .../selection_resolution_intersect.svg | 2 +- .../selection_resolution_intersect.vg.json | 190 ++++++----- .../compiled/selection_resolution_union.svg | 2 +- .../selection_resolution_union.vg.json | 190 ++++++----- .../compiled/selection_toggle_altKey.vg.json | 12 +- .../selection_toggle_altKey_shiftKey.vg.json | 12 +- .../selection_toggle_shiftKey.vg.json | 12 +- .../selection_translate_brush_drag.vg.json | 9 +- ...lection_translate_brush_shift-drag.vg.json | 9 +- ...lection_translate_scatterplot_drag.vg.json | 11 +- ...n_translate_scatterplot_shift-drag.vg.json | 11 +- .../compiled/selection_type_interval.vg.json | 9 +- .../selection_type_interval_invert.vg.json | 9 +- .../compiled/selection_type_multi.vg.json | 9 +- .../compiled/selection_type_single.vg.json | 13 +- .../selection_type_single_dblclick.vg.json | 13 +- .../selection_zoom_brush_shift-wheel.vg.json | 9 +- .../selection_zoom_brush_wheel.vg.json | 9 +- ...ction_zoom_scatterplot_shift-wheel.vg.json | 11 +- .../selection_zoom_scatterplot_wheel.vg.json | 11 +- examples/compiled/trellis_selections.vg.json | 36 ++- examples/compiled/vconcat_flatten.vg.json | 13 +- 72 files changed, 1233 insertions(+), 622 deletions(-) diff --git a/examples/compiled/circle_bubble_health_income.vg.json b/examples/compiled/circle_bubble_health_income.vg.json index c704641070..97455bdf04 100644 --- a/examples/compiled/circle_bubble_health_income.vg.json +++ b/examples/compiled/circle_bubble_health_income.vg.json @@ -29,6 +29,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "view", "update": "vlSelectionResolve(\"view_store\")"}, { "name": "view_income", "on": [ @@ -60,10 +61,14 @@ "on": [ { "events": [{"signal": "view_income"}, {"signal": "view_health"}], - "update": "view_income && view_health ? {unit: \"\", intervals: [{encoding: \"x\", field: \"income\", extent: view_income}, {encoding: \"y\", field: \"health\", extent: view_health}]} : null" + "update": "view_income && view_health ? {unit: \"\", fields: view_tuple_fields, values: [view_income, view_health]} : null" } ] }, + { + "name": "view_tuple_fields", + "update": "[{\"field\":\"income\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"health\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "view_translate_anchor", "value": {}, @@ -156,7 +161,7 @@ "name": "x", "type": "log", "domain": {"data": "source_0", "field": "income"}, - "domainRaw": {"signal": "view_income"}, + "domainRaw": {"signal": "view[\"income\"]"}, "range": [0, {"signal": "width"}], "nice": true }, @@ -164,7 +169,7 @@ "name": "y", "type": "linear", "domain": {"data": "source_0", "field": "health"}, - "domainRaw": {"signal": "view_health"}, + "domainRaw": {"signal": "view[\"health\"]"}, "range": [{"signal": "height"}, 0], "zero": false, "nice": true diff --git a/examples/compiled/concat_bar_layer_circle.vg.json b/examples/compiled/concat_bar_layer_circle.vg.json index 0095a93fa7..4407fe4cba 100644 --- a/examples/compiled/concat_bar_layer_circle.vg.json +++ b/examples/compiled/concat_bar_layer_circle.vg.json @@ -131,7 +131,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))" + "expr": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))" }, { "type": "aggregate", @@ -160,10 +160,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {Major_Genre: data(\"pts_store\")[0].values[0]}" - } + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -315,11 +312,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", encodings: [\"x\"], fields: [\"Major_Genre\"], values: [datum[\"Major_Genre\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", fields: pts_tuple_fields, values: [datum[\"Major_Genre\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Major_Genre\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -344,7 +345,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": "steelblue" }, {"value": "grey"} diff --git a/examples/compiled/interactive_area_brush.vg.json b/examples/compiled/interactive_area_brush.vg.json index d84c42a186..eaf42caa8e 100644 --- a/examples/compiled/interactive_area_brush.vg.json +++ b/examples/compiled/interactive_area_brush.vg.json @@ -36,7 +36,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "formula", @@ -61,6 +61,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -125,10 +126,14 @@ "on": [ { "events": [{"signal": "brush_yearmonth_date"}], - "update": "brush_yearmonth_date ? {unit: \"layer_0\", intervals: [{encoding: \"x\", field: \"yearmonth_date\", extent: brush_yearmonth_date}]} : null" + "update": "brush_yearmonth_date ? {unit: \"layer_0\", fields: brush_tuple_fields, values: [brush_yearmonth_date]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"yearmonth_date\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, diff --git a/examples/compiled/interactive_brush.vg.json b/examples/compiled/interactive_brush.vg.json index c5e3d0f2e1..fc436bd5c9 100644 --- a/examples/compiled/interactive_brush.vg.json +++ b/examples/compiled/interactive_brush.vg.json @@ -25,6 +25,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -147,10 +148,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -290,7 +295,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/interactive_concat_layer.vg.json b/examples/compiled/interactive_concat_layer.vg.json index a1154db233..3dfe9c8531 100644 --- a/examples/compiled/interactive_concat_layer.vg.json +++ b/examples/compiled/interactive_concat_layer.vg.json @@ -131,7 +131,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))" + "expr": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))" }, { "type": "aggregate", @@ -160,10 +160,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {Major_Genre: data(\"pts_store\")[0].values[0]}" - } + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -314,11 +311,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", encodings: [\"x\"], fields: [\"Major_Genre\"], values: [datum[\"Major_Genre\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", fields: pts_tuple_fields, values: [datum[\"Major_Genre\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Major_Genre\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -343,7 +344,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": "steelblue" }, {"value": "grey"} diff --git a/examples/compiled/interactive_dashboard_europe_pop.vg.json b/examples/compiled/interactive_dashboard_europe_pop.vg.json index 1f1b0ae0b5..1a8f1a66f0 100644 --- a/examples/compiled/interactive_dashboard_europe_pop.vg.json +++ b/examples/compiled/interactive_dashboard_europe_pop.vg.json @@ -339,7 +339,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -419,10 +420,14 @@ "on": [ { "events": [{"signal": "brush_Country"}], - "update": "brush_Country ? {unit: \"concat_0\", intervals: [{encoding: \"y\", field: \"Country\", extent: brush_Country}]} : null" + "update": "brush_Country ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_Country]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Country\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -561,7 +566,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (!(vlInterval(\"brush_store\", datum)))", + "test": "!(length(data(\"brush_store\"))) || (!(vlSelectionTest(\"brush_store\", datum)))", "value": "steelblue" }, {"value": "goldenrod"} @@ -728,10 +733,14 @@ "on": [ { "events": [{"signal": "brush_Country"}], - "update": "brush_Country ? {unit: \"concat_1\", intervals: [{encoding: \"y\", field: \"Country\", extent: brush_Country}]} : null" + "update": "brush_Country ? {unit: \"concat_1\", fields: brush_tuple_fields, values: [brush_Country]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Country\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -870,7 +879,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (!(vlInterval(\"brush_store\", datum)))", + "test": "!(length(data(\"brush_store\"))) || (!(vlSelectionTest(\"brush_store\", datum)))", "value": "steelblue" }, {"value": "goldenrod"} @@ -1098,10 +1107,14 @@ {"signal": "brush_Population_ages_65_and_above_of_total"}, {"signal": "brush_Population_ages_15_64_of_total"} ], - "update": "brush_Population_ages_65_and_above_of_total && brush_Population_ages_15_64_of_total ? {unit: \"concat_2\", intervals: [{encoding: \"x\", field: \"Population_ages_65_and_above_of_total\", extent: brush_Population_ages_65_and_above_of_total}, {encoding: \"y\", field: \"Population_ages_15_64_of_total\", extent: brush_Population_ages_15_64_of_total}]} : null" + "update": "brush_Population_ages_65_and_above_of_total && brush_Population_ages_15_64_of_total ? {unit: \"concat_2\", fields: brush_tuple_fields, values: [brush_Population_ages_65_and_above_of_total, brush_Population_ages_15_64_of_total]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Population_ages_65_and_above_of_total\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Population_ages_15_64_of_total\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1248,7 +1261,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (!(vlInterval(\"brush_store\", datum)))", + "test": "!(length(data(\"brush_store\"))) || (!(vlSelectionTest(\"brush_store\", datum)))", "value": "steelblue" }, {"value": "goldenrod"} diff --git a/examples/compiled/interactive_layered_crossfilter.vg.json b/examples/compiled/interactive_layered_crossfilter.vg.json index f969ea43db..79099bdbe8 100644 --- a/examples/compiled/interactive_layered_crossfilter.vg.json +++ b/examples/compiled/interactive_layered_crossfilter.vg.json @@ -59,7 +59,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -131,7 +131,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -191,7 +191,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -210,7 +210,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -291,10 +292,14 @@ "on": [ { "events": [{"signal": "brush_distance"}], - "update": "brush_distance ? {unit: \"child_distance_layer_0\", intervals: [{encoding: \"x\", field: \"distance\", extent: brush_distance}]} : null" + "update": "brush_distance ? {unit: \"child_distance_layer_0\", fields: brush_tuple_fields, values: [brush_distance]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"distance\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -635,10 +640,14 @@ "on": [ { "events": [{"signal": "brush_delay"}], - "update": "brush_delay ? {unit: \"child_delay_layer_0\", intervals: [{encoding: \"x\", field: \"delay\", extent: brush_delay}]} : null" + "update": "brush_delay ? {unit: \"child_delay_layer_0\", fields: brush_tuple_fields, values: [brush_delay]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"delay\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -979,10 +988,14 @@ "on": [ { "events": [{"signal": "brush_time"}], - "update": "brush_time ? {unit: \"child_time_layer_0\", intervals: [{encoding: \"x\", field: \"time\", extent: brush_time}]} : null" + "update": "brush_time ? {unit: \"child_time_layer_0\", fields: brush_tuple_fields, values: [brush_time]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"time\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, diff --git a/examples/compiled/interactive_layered_crossfilter_discrete.vg.json b/examples/compiled/interactive_layered_crossfilter_discrete.vg.json index f353e4fb8b..c6083b4d9e 100644 --- a/examples/compiled/interactive_layered_crossfilter_discrete.vg.json +++ b/examples/compiled/interactive_layered_crossfilter_discrete.vg.json @@ -59,7 +59,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlMulti(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -131,7 +131,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlMulti(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -191,7 +191,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlMulti(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -210,7 +210,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -233,11 +234,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_distance_layer_0\", encodings: [\"x\"], fields: [\"distance\"], values: [[datum[\"bin_maxbins_20_distance\"], datum[\"bin_maxbins_20_distance_end\"]]], \"bin_distance\": 1} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_distance_layer_0\", fields: brush_tuple_fields, values: [[datum[\"bin_maxbins_20_distance\"], datum[\"bin_maxbins_20_distance_end\"]]]} : null", "force": true } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"distance\",\"channel\":\"x\",\"type\":\"R-RE\"}]" + }, { "name": "brush_toggle", "value": false, @@ -374,11 +379,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_delay_layer_0\", encodings: [\"x\"], fields: [\"delay\"], values: [[datum[\"bin_maxbins_20_delay\"], datum[\"bin_maxbins_20_delay_end\"]]], \"bin_delay\": 1} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_delay_layer_0\", fields: brush_tuple_fields, values: [[datum[\"bin_maxbins_20_delay\"], datum[\"bin_maxbins_20_delay_end\"]]]} : null", "force": true } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"delay\",\"channel\":\"x\",\"type\":\"R-RE\"}]" + }, { "name": "brush_toggle", "value": false, @@ -515,11 +524,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_time_layer_0\", encodings: [\"x\"], fields: [\"time\"], values: [[datum[\"bin_maxbins_20_time\"], datum[\"bin_maxbins_20_time_end\"]]], \"bin_time\": 1} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"child_time_layer_0\", fields: brush_tuple_fields, values: [[datum[\"bin_maxbins_20_time\"], datum[\"bin_maxbins_20_time_end\"]]]} : null", "force": true } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"time\",\"channel\":\"x\",\"type\":\"R-RE\"}]" + }, { "name": "brush_toggle", "value": false, diff --git a/examples/compiled/interactive_multi_line_tooltip.vg.json b/examples/compiled/interactive_multi_line_tooltip.vg.json index 27e5edbf20..06d71122b4 100644 --- a/examples/compiled/interactive_multi_line_tooltip.vg.json +++ b/examples/compiled/interactive_multi_line_tooltip.vg.json @@ -16,7 +16,10 @@ "name": "data_0", "source": "source_0", "transform": [ - {"type": "filter", "expr": "(vlSingle(\"tooltip_store\", datum))"} + { + "type": "filter", + "expr": "(vlSelectionTest(\"tooltip_store\", datum))" + } ] }, { @@ -42,21 +45,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "tooltip", - "update": "data(\"tooltip_store\").length && {date: data(\"tooltip_store\")[0].values[0]}" - }, + {"name": "tooltip", "update": "vlSelectionResolve(\"tooltip_store\")"}, { "name": "tooltip_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"layer_0_layer_1\", encodings: [\"x\"], fields: [\"date\"], values: [(item().isVoronoi ? datum.datum : datum)[\"date\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"layer_0_layer_1\", fields: tooltip_tuple_fields, values: [(item().isVoronoi ? datum.datum : datum)[\"date\"]]} : null", "force": true } ] }, + { + "name": "tooltip_tuple_fields", + "update": "[{\"field\":\"date\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "tooltip_modify", "on": [ @@ -115,7 +119,7 @@ "encode": { "update": { "opacity": [ - {"test": "(vlSingle(\"tooltip_store\", datum))", "value": 1}, + {"test": "(vlSelectionTest(\"tooltip_store\", datum))", "value": 1}, {"value": 0} ], "fill": [ diff --git a/examples/compiled/interactive_overview_detail.vg.json b/examples/compiled/interactive_overview_detail.vg.json index 8b2dc35cfb..2057743fa3 100644 --- a/examples/compiled/interactive_overview_detail.vg.json +++ b/examples/compiled/interactive_overview_detail.vg.json @@ -20,7 +20,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -186,10 +187,14 @@ "on": [ { "events": [{"signal": "brush_date"}], - "update": "brush_date ? {unit: \"concat_1\", intervals: [{encoding: \"x\", field: \"date\", extent: brush_date}]} : null" + "update": "brush_date ? {unit: \"concat_1\", fields: brush_tuple_fields, values: [brush_date]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"date\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -421,9 +426,7 @@ "name": "concat_0_x", "type": "time", "domain": {"data": "source_0", "field": "date"}, - "domainRaw": { - "signal": "vlIntervalDomain(\"brush_store\", null, \"date\")" - }, + "domainRaw": {"signal": "brush[\"date\"]"}, "range": [0, {"signal": "width"}] }, { diff --git a/examples/compiled/interactive_paintbrush.vg.json b/examples/compiled/interactive_paintbrush.vg.json index 38c00f0d41..8d5378f7ec 100644 --- a/examples/compiled/interactive_paintbrush.vg.json +++ b/examples/compiled/interactive_paintbrush.vg.json @@ -26,17 +26,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -87,7 +95,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "value": 300 }, {"value": 50} diff --git a/examples/compiled/interactive_paintbrush_color.vg.json b/examples/compiled/interactive_paintbrush_color.vg.json index 6c316653b9..b9c6677632 100644 --- a/examples/compiled/interactive_paintbrush_color.vg.json +++ b/examples/compiled/interactive_paintbrush_color.vg.json @@ -26,17 +26,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -72,7 +80,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/interactive_paintbrush_color_nearest.vg.json b/examples/compiled/interactive_paintbrush_color_nearest.vg.json index 53047eeebc..92b8a3c567 100644 --- a/examples/compiled/interactive_paintbrush_color_nearest.vg.json +++ b/examples/compiled/interactive_paintbrush_color_nearest.vg.json @@ -26,17 +26,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -72,7 +80,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/interactive_paintbrush_interval.vg.json b/examples/compiled/interactive_paintbrush_interval.vg.json index 7383a46c6b..4bbf12d8e4 100644 --- a/examples/compiled/interactive_paintbrush_interval.vg.json +++ b/examples/compiled/interactive_paintbrush_interval.vg.json @@ -25,6 +25,10 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_x", "value": [], @@ -147,10 +151,14 @@ {"signal": "paintbrush_Horsepower"}, {"signal": "paintbrush_Miles_per_Gallon"} ], - "update": "paintbrush_Horsepower && paintbrush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: paintbrush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: paintbrush_Miles_per_Gallon}]} : null" + "update": "paintbrush_Horsepower && paintbrush_Miles_per_Gallon ? {unit: \"\", fields: paintbrush_tuple_fields, values: [paintbrush_Horsepower, paintbrush_Miles_per_Gallon]} : null" } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "paintbrush_translate_anchor", "value": {}, @@ -302,7 +310,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"paintbrush_store\"))) || (vlInterval(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "value": 300 }, {"value": 50} diff --git a/examples/compiled/interactive_paintbrush_simple_all.vg.json b/examples/compiled/interactive_paintbrush_simple_all.vg.json index 95b065ded9..16c3e5667c 100644 --- a/examples/compiled/interactive_paintbrush_simple_all.vg.json +++ b/examples/compiled/interactive_paintbrush_simple_all.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -86,7 +94,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "value": 300 }, {"value": 50} diff --git a/examples/compiled/interactive_paintbrush_simple_none.vg.json b/examples/compiled/interactive_paintbrush_simple_none.vg.json index 73e0cbbb5e..80cb0c6fd4 100644 --- a/examples/compiled/interactive_paintbrush_simple_none.vg.json +++ b/examples/compiled/interactive_paintbrush_simple_none.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -85,7 +93,10 @@ "x": {"scale": "x", "field": "Horsepower"}, "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ - {"test": "(vlMulti(\"paintbrush_store\", datum))", "value": 300}, + { + "test": "(vlSelectionTest(\"paintbrush_store\", datum))", + "value": 300 + }, {"value": 50} ] } diff --git a/examples/compiled/interactive_panzoom_splom.vg.json b/examples/compiled/interactive_panzoom_splom.vg.json index b68d258a21..3464f4c699 100644 --- a/examples/compiled/interactive_panzoom_splom.vg.json +++ b/examples/compiled/interactive_panzoom_splom.vg.json @@ -27,6 +27,10 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "grid", + "update": "{Miles_per_Gallon: grid_Miles_per_Gallon, Horsepower: grid_Horsepower, Acceleration: grid_Acceleration}" + }, {"name": "grid_Miles_per_Gallon"}, {"name": "grid_Horsepower"}, {"name": "grid_Acceleration"} @@ -82,10 +86,14 @@ {"signal": "grid_Miles_per_Gallon"}, {"signal": "grid_Horsepower"} ], - "update": "grid_Miles_per_Gallon && grid_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Miles_per_Gallon && grid_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon, grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -276,10 +284,14 @@ {"signal": "grid_Acceleration"}, {"signal": "grid_Horsepower"} ], - "update": "grid_Acceleration && grid_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: grid_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Acceleration && grid_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration, grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -439,11 +451,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Horsepower_Horsepower_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Horsepower_Horsepower_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -453,17 +465,21 @@ "on": [ { "events": [{"signal": "grid_Horsepower"}], - "update": "grid_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mousedown"}], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Horsepower_Horsepower_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Horsepower_Horsepower_x\")}" } ] }, @@ -647,10 +663,14 @@ {"signal": "grid_Miles_per_Gallon"}, {"signal": "grid_Acceleration"} ], - "update": "grid_Miles_per_Gallon && grid_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Miles_per_Gallon && grid_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon, grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -810,11 +830,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Acceleration_Acceleration_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Acceleration_Acceleration_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -824,17 +844,21 @@ "on": [ { "events": [{"signal": "grid_Acceleration"}], - "update": "grid_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mousedown"}], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Acceleration_Acceleration_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Acceleration_Acceleration_x\")}" } ] }, @@ -1018,10 +1042,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Acceleration"} ], - "update": "grid_Horsepower && grid_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Horsepower && grid_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -1181,11 +1209,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Miles_per_Gallon_Miles_per_Gallon_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Miles_per_Gallon_Miles_per_Gallon_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -1195,17 +1223,21 @@ "on": [ { "events": [{"signal": "grid_Miles_per_Gallon"}], - "update": "grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mousedown"}], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Miles_per_Gallon_Miles_per_Gallon_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Miles_per_Gallon_Miles_per_Gallon_x\")}" } ] }, @@ -1389,10 +1421,14 @@ {"signal": "grid_Acceleration"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Acceleration && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: grid_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Acceleration && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -1583,10 +1619,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -1745,7 +1785,7 @@ "name": "child_Horsepower_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1754,7 +1794,7 @@ "name": "child_Horsepower_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1763,7 +1803,7 @@ "name": "child_Horsepower_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1772,7 +1812,7 @@ "name": "child_Horsepower_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1781,7 +1821,7 @@ "name": "child_Horsepower_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1790,7 +1830,7 @@ "name": "child_Horsepower_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1799,7 +1839,7 @@ "name": "child_Acceleration_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1808,7 +1848,7 @@ "name": "child_Acceleration_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1817,7 +1857,7 @@ "name": "child_Acceleration_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1826,7 +1866,7 @@ "name": "child_Acceleration_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1835,7 +1875,7 @@ "name": "child_Acceleration_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1844,7 +1884,7 @@ "name": "child_Acceleration_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1853,7 +1893,7 @@ "name": "child_Miles_per_Gallon_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1862,7 +1902,7 @@ "name": "child_Miles_per_Gallon_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1871,7 +1911,7 @@ "name": "child_Miles_per_Gallon_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1880,7 +1920,7 @@ "name": "child_Miles_per_Gallon_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -1889,7 +1929,7 @@ "name": "child_Miles_per_Gallon_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -1898,7 +1938,7 @@ "name": "child_Miles_per_Gallon_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/interactive_panzoom_vconcat_shared.vg.json b/examples/compiled/interactive_panzoom_vconcat_shared.vg.json index c8a2d90a80..7c16b3f955 100644 --- a/examples/compiled/interactive_panzoom_vconcat_shared.vg.json +++ b/examples/compiled/interactive_panzoom_vconcat_shared.vg.json @@ -28,6 +28,10 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "region", + "update": "{Horsepower: region_Horsepower, Miles_per_Gallon: region_Miles_per_Gallon}" + }, {"name": "region_Horsepower"}, {"name": "region_Miles_per_Gallon"} ], @@ -85,10 +89,14 @@ {"signal": "region_Horsepower"}, {"signal": "region_Miles_per_Gallon"} ], - "update": "region_Horsepower && region_Miles_per_Gallon ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: region_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: region_Miles_per_Gallon}]} : null" + "update": "region_Horsepower && region_Miles_per_Gallon ? {unit: \"concat_0\", fields: region_tuple_fields, values: [region_Horsepower, region_Miles_per_Gallon]} : null" } ] }, + { + "name": "region_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "region_translate_anchor", "value": {}, @@ -326,7 +334,7 @@ "name": "x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "region_Horsepower"}, + "domainRaw": {"signal": "region[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -335,7 +343,7 @@ "name": "concat_0_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "region_Miles_per_Gallon"}, + "domainRaw": {"signal": "region[\"Miles_per_Gallon\"]"}, "range": [{"signal": "concat_0_height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/interactive_query_widgets.vg.json b/examples/compiled/interactive_query_widgets.vg.json index 87984d4bad..2c0abf5fdb 100644 --- a/examples/compiled/interactive_query_widgets.vg.json +++ b/examples/compiled/interactive_query_widgets.vg.json @@ -25,7 +25,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"CylYr_store\"))) || (vlSingle(\"CylYr_store\", datum))" + "expr": "!(length(data(\"CylYr_store\"))) || (vlSelectionTest(\"CylYr_store\", datum))" } ] } @@ -60,13 +60,14 @@ ], "bind": {"input": "range", "min": 3, "max": 8, "step": 1} }, + {"name": "CylYr", "update": "vlSelectionResolve(\"CylYr_store\")"}, { - "name": "CylYr", - "update": "data(\"CylYr_store\").length && {Cylinders: data(\"CylYr_store\")[0].values[0], Year: data(\"CylYr_store\")[0].values[1]}" + "name": "CylYr_tuple", + "update": "CylYr_Cylinders && CylYr_Year ? {fields: CylYr_tuple_fields, values: [CylYr_Cylinders, CylYr_Year]} : null" }, { - "name": "CylYr_tuple", - "update": "CylYr_Cylinders && CylYr_Year ? {fields: [\"Cylinders\", \"Year\"], values: [CylYr_Cylinders, CylYr_Year]} : null" + "name": "CylYr_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"},{\"field\":\"Year\",\"type\":\"E\"}]" }, { "name": "CylYr_modify", @@ -93,7 +94,7 @@ "value": null }, { - "test": "!(length(data(\"CylYr_store\"))) || (vlSingle(\"CylYr_store\", datum))", + "test": "!(length(data(\"CylYr_store\"))) || (vlSelectionTest(\"CylYr_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/interactive_seattle_weather.vg.json b/examples/compiled/interactive_seattle_weather.vg.json index 944dad131d..188d31c8f8 100644 --- a/examples/compiled/interactive_seattle_weather.vg.json +++ b/examples/compiled/interactive_seattle_weather.vg.json @@ -23,7 +23,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -51,7 +51,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"click_store\"))) || (vlMulti(\"click_store\", datum))" + "expr": "!(length(data(\"click_store\"))) || (vlSelectionTest(\"click_store\", datum))" }, { "type": "formula", @@ -74,7 +74,9 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, + {"name": "click", "update": "vlSelectionResolve(\"click_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -158,10 +160,14 @@ "on": [ { "events": [{"signal": "brush_monthdate_date"}], - "update": "brush_monthdate_date ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"monthdate_date\", extent: brush_monthdate_date}]} : null" + "update": "brush_monthdate_date ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_monthdate_date]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"monthdate_date\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -308,7 +314,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "weather" }, @@ -436,11 +442,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", encodings: [\"color\"], fields: [\"weather\"], values: [datum[\"weather\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_1\", fields: click_tuple_fields, values: [datum[\"weather\"]]} : null", "force": true } ] }, + { + "name": "click_tuple_fields", + "update": "[{\"field\":\"weather\",\"channel\":\"color\",\"type\":\"E\"}]" + }, { "name": "click_toggle", "value": false, @@ -475,7 +485,7 @@ "value": null }, { - "test": "!(length(data(\"click_store\"))) || (vlMulti(\"click_store\", datum))", + "test": "!(length(data(\"click_store\"))) || (vlSelectionTest(\"click_store\", datum))", "scale": "color", "field": "weather" }, diff --git a/examples/compiled/interactive_splom.svg b/examples/compiled/interactive_splom.svg index 7bf956f845..3a29208d06 100644 --- a/examples/compiled/interactive_splom.svg +++ b/examples/compiled/interactive_splom.svg @@ -1 +1 @@ -01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file +01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file diff --git a/examples/compiled/interactive_splom.vg.json b/examples/compiled/interactive_splom.vg.json index a826beb1eb..3d8d1b67cb 100644 --- a/examples/compiled/interactive_splom.vg.json +++ b/examples/compiled/interactive_splom.vg.json @@ -28,6 +28,14 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "brush", + "update": "vlSelectionResolve(\"brush_store\", \"union\")" + }, + { + "name": "grid", + "update": "{Miles_per_Gallon: grid_Miles_per_Gallon, Horsepower: grid_Horsepower, Acceleration: grid_Acceleration}" + }, {"name": "grid_Miles_per_Gallon"}, {"name": "grid_Horsepower"}, {"name": "grid_Acceleration"} @@ -173,10 +181,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -299,10 +311,14 @@ {"signal": "grid_Miles_per_Gallon"}, {"signal": "grid_Horsepower"} ], - "update": "grid_Miles_per_Gallon && grid_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Miles_per_Gallon && grid_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon, grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -426,7 +442,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -650,10 +666,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -776,10 +796,14 @@ {"signal": "grid_Acceleration"}, {"signal": "grid_Horsepower"} ], - "update": "grid_Acceleration && grid_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: grid_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Acceleration && grid_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration, grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -903,7 +927,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1002,7 +1026,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -1014,7 +1038,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -1033,19 +1057,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[1])]" + "update": "[scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -1053,24 +1077,28 @@ "name": "brush_Horsepower", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Horsepower_Horsepower_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Horsepower_Horsepower_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_y\", brush_y)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_y\", brush_y)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_x\", brush_x)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_x\", brush_x)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Horsepower"}], - "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1084,7 +1112,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -1162,11 +1190,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Horsepower_Horsepower_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Horsepower_Horsepower_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -1176,10 +1204,14 @@ "on": [ { "events": [{"signal": "grid_Horsepower"}], - "update": "grid_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: grid_Horsepower}]} : null" + "update": "grid_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -1192,7 +1224,7 @@ "filter": ["!event.shiftKey"] } ], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Horsepower_Horsepower_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Horsepower_Horsepower_x\")}" } ] }, @@ -1274,10 +1306,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -1303,7 +1335,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1330,12 +1362,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1524,10 +1556,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1650,10 +1686,14 @@ {"signal": "grid_Miles_per_Gallon"}, {"signal": "grid_Acceleration"} ], - "update": "grid_Miles_per_Gallon && grid_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Miles_per_Gallon && grid_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon, grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -1777,7 +1817,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1876,7 +1916,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -1888,7 +1928,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -1907,19 +1947,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[1])]" + "update": "[scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -1927,24 +1967,28 @@ "name": "brush_Acceleration", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Acceleration_Acceleration_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Acceleration_Acceleration_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_y\", brush_y)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_y\", brush_y)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_x\", brush_x)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_x\", brush_x)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Acceleration"}], - "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1958,7 +2002,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -2036,11 +2080,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Acceleration_Acceleration_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Acceleration_Acceleration_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -2050,10 +2094,14 @@ "on": [ { "events": [{"signal": "grid_Acceleration"}], - "update": "grid_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -2066,7 +2114,7 @@ "filter": ["!event.shiftKey"] } ], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Acceleration_Acceleration_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Acceleration_Acceleration_x\")}" } ] }, @@ -2148,10 +2196,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -2177,7 +2225,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -2204,12 +2252,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -2398,10 +2446,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2524,10 +2576,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Acceleration"} ], - "update": "grid_Horsepower && grid_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Horsepower && grid_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -2651,7 +2707,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -2750,7 +2806,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -2762,7 +2818,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -2781,19 +2837,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[1])]" + "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -2801,24 +2857,28 @@ "name": "brush_Miles_per_Gallon", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Miles_per_Gallon"}], - "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2832,7 +2892,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -2910,11 +2970,11 @@ "on": [ { "events": {"signal": "grid_translate_delta"}, - "update": "panLinear(grid_translate_anchor.extent_y, grid_translate_delta.y / height)" + "update": "panLinear(grid_translate_anchor.extent_x, -grid_translate_delta.x / width)" }, { "events": {"signal": "grid_zoom_delta"}, - "update": "zoomLinear(domain(\"child_Miles_per_Gallon_Miles_per_Gallon_y\"), grid_zoom_anchor.y, grid_zoom_delta)" + "update": "zoomLinear(domain(\"child_Miles_per_Gallon_Miles_per_Gallon_x\"), grid_zoom_anchor.x, grid_zoom_delta)" } ], "push": "outer" @@ -2924,10 +2984,14 @@ "on": [ { "events": [{"signal": "grid_Miles_per_Gallon"}], - "update": "grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: grid_tuple_fields, values: [grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -2940,7 +3004,7 @@ "filter": ["!event.shiftKey"] } ], - "update": "{x: x(unit), y: y(unit), extent_y: domain(\"child_Miles_per_Gallon_Miles_per_Gallon_y\")}" + "update": "{x: x(unit), y: y(unit), extent_x: domain(\"child_Miles_per_Gallon_Miles_per_Gallon_x\")}" } ] }, @@ -3022,10 +3086,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -3051,7 +3115,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -3078,12 +3142,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -3272,10 +3336,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -3398,10 +3466,14 @@ {"signal": "grid_Acceleration"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Acceleration && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: grid_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Acceleration && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: grid_tuple_fields, values: [grid_Acceleration, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -3525,7 +3597,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -3749,10 +3821,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -3875,10 +3951,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -4002,7 +4082,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -4104,7 +4184,7 @@ "name": "child_Horsepower_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4113,7 +4193,7 @@ "name": "child_Horsepower_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4122,7 +4202,7 @@ "name": "child_Horsepower_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4131,7 +4211,7 @@ "name": "child_Horsepower_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4140,7 +4220,7 @@ "name": "child_Horsepower_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4149,7 +4229,7 @@ "name": "child_Horsepower_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4158,7 +4238,7 @@ "name": "child_Acceleration_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4167,7 +4247,7 @@ "name": "child_Acceleration_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4176,7 +4256,7 @@ "name": "child_Acceleration_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4185,7 +4265,7 @@ "name": "child_Acceleration_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4194,7 +4274,7 @@ "name": "child_Acceleration_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4203,7 +4283,7 @@ "name": "child_Acceleration_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4212,7 +4292,7 @@ "name": "child_Miles_per_Gallon_Miles_per_Gallon_x", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4221,7 +4301,7 @@ "name": "child_Miles_per_Gallon_Miles_per_Gallon_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4230,7 +4310,7 @@ "name": "child_Miles_per_Gallon_Acceleration_x", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4239,7 +4319,7 @@ "name": "child_Miles_per_Gallon_Acceleration_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true @@ -4248,7 +4328,7 @@ "name": "child_Miles_per_Gallon_Horsepower_x", "type": "linear", "domain": {"data": "source_0", "field": "Horsepower"}, - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -4257,7 +4337,7 @@ "name": "child_Miles_per_Gallon_Horsepower_y", "type": "linear", "domain": {"data": "source_0", "field": "Miles_per_Gallon"}, - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/interactive_stocks_nearest_index.vg.json b/examples/compiled/interactive_stocks_nearest_index.vg.json index a4df231e72..7bfc563ea9 100644 --- a/examples/compiled/interactive_stocks_nearest_index.vg.json +++ b/examples/compiled/interactive_stocks_nearest_index.vg.json @@ -18,7 +18,7 @@ "transform": [ { "type": "filter", - "expr": "(index.date) && (!(length(data(\"index_store\"))) || (vlSingle(\"index_store\", datum)))" + "expr": "(index.date) && (!(length(data(\"index_store\"))) || (vlSelectionTest(\"index_store\", datum)))" } ] } @@ -31,21 +31,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "index", - "update": "data(\"index_store\").length && {date: data(\"index_store\")[0].values[0]}" - }, + {"name": "index", "update": "vlSelectionResolve(\"index_store\")"}, { "name": "index_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "mousemove"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"layer_1\", encodings: [\"x\"], fields: [\"date\"], values: [(item().isVoronoi ? datum.datum : datum)[\"date\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"layer_1\", fields: index_tuple_fields, values: [(item().isVoronoi ? datum.datum : datum)[\"date\"]]} : null", "force": true } ] }, + { + "name": "index_tuple_fields", + "update": "[{\"field\":\"date\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "index_modify", "on": [ diff --git a/examples/compiled/isotype_grid.vg.json b/examples/compiled/isotype_grid.vg.json index 2ae32986bf..18aaf7e3b5 100644 --- a/examples/compiled/isotype_grid.vg.json +++ b/examples/compiled/isotype_grid.vg.json @@ -129,6 +129,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "highlight", "update": "vlSelectionResolve(\"highlight_store\")"}, { "name": "highlight_x", "value": [], @@ -242,10 +243,14 @@ "on": [ { "events": [{"signal": "highlight_col"}, {"signal": "highlight_row"}], - "update": "highlight_col && highlight_row ? {unit: \"\", intervals: [{encoding: \"x\", field: \"col\", extent: highlight_col}, {encoding: \"y\", field: \"row\", extent: highlight_row}]} : null" + "update": "highlight_col && highlight_row ? {unit: \"\", fields: highlight_tuple_fields, values: [highlight_col, highlight_row]} : null" } ] }, + { + "name": "highlight_tuple_fields", + "update": "[{\"field\":\"col\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"row\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "highlight_translate_anchor", "value": {}, @@ -378,7 +383,7 @@ "opacity": {"value": 0.7}, "fill": [ { - "test": "!(length(data(\"highlight_store\"))) || (vlInterval(\"highlight_store\", datum))", + "test": "!(length(data(\"highlight_store\"))) || (vlSelectionTest(\"highlight_store\", datum))", "value": "rgb(194,81,64)" }, {"value": "rgb(167,165,156)"} diff --git a/examples/compiled/selection_bind_cylyr.vg.json b/examples/compiled/selection_bind_cylyr.vg.json index cfddf2212b..b587fae3f3 100644 --- a/examples/compiled/selection_bind_cylyr.vg.json +++ b/examples/compiled/selection_bind_cylyr.vg.json @@ -49,13 +49,14 @@ ], "bind": {"input": "range", "min": 3, "max": 8, "step": 1} }, + {"name": "CylYr", "update": "vlSelectionResolve(\"CylYr_store\")"}, { - "name": "CylYr", - "update": "data(\"CylYr_store\").length && {Cylinders: data(\"CylYr_store\")[0].values[0], Year: data(\"CylYr_store\")[0].values[1]}" + "name": "CylYr_tuple", + "update": "CylYr_Cylinders && CylYr_Year ? {fields: CylYr_tuple_fields, values: [CylYr_Cylinders, CylYr_Year]} : null" }, { - "name": "CylYr_tuple", - "update": "CylYr_Cylinders && CylYr_Year ? {fields: [\"Cylinders\", \"Year\"], values: [CylYr_Cylinders, CylYr_Year]} : null" + "name": "CylYr_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"},{\"field\":\"Year\",\"type\":\"E\"}]" }, { "name": "CylYr_modify", @@ -82,7 +83,7 @@ "value": null }, { - "test": "!(length(data(\"CylYr_store\"))) || (vlSingle(\"CylYr_store\", datum))", + "test": "!(length(data(\"CylYr_store\"))) || (vlSelectionTest(\"CylYr_store\", datum))", "scale": "color", "field": "Origin" }, @@ -95,7 +96,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"CylYr_store\"))) || (vlSingle(\"CylYr_store\", datum))", + "test": "!(length(data(\"CylYr_store\"))) || (vlSelectionTest(\"CylYr_store\", datum))", "value": 100 }, {"value": 50} diff --git a/examples/compiled/selection_bind_origin.vg.json b/examples/compiled/selection_bind_origin.vg.json index 49decc47f8..5fc309ea13 100644 --- a/examples/compiled/selection_bind_origin.vg.json +++ b/examples/compiled/selection_bind_origin.vg.json @@ -35,13 +35,14 @@ ], "bind": {"input": "select", "options": ["Europe", "Japan", "USA"]} }, + {"name": "org", "update": "vlSelectionResolve(\"org_store\")"}, { - "name": "org", - "update": "data(\"org_store\").length && {Origin: data(\"org_store\")[0].values[0]}" + "name": "org_tuple", + "update": "org_Origin ? {fields: org_tuple_fields, values: [org_Origin]} : null" }, { - "name": "org_tuple", - "update": "org_Origin ? {fields: [\"Origin\"], values: [org_Origin]} : null" + "name": "org_tuple_fields", + "update": "[{\"field\":\"Origin\",\"type\":\"E\"}]" }, { "name": "org_modify", @@ -75,7 +76,7 @@ "value": null }, { - "test": "!(length(data(\"org_store\"))) || (vlSingle(\"org_store\", datum))", + "test": "!(length(data(\"org_store\"))) || (vlSelectionTest(\"org_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/selection_brush_timeunit.vg.json b/examples/compiled/selection_brush_timeunit.vg.json index eb097ba0ae..7e1a4b50f7 100644 --- a/examples/compiled/selection_brush_timeunit.vg.json +++ b/examples/compiled/selection_brush_timeunit.vg.json @@ -38,7 +38,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "formula", @@ -57,7 +57,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -140,10 +141,14 @@ "on": [ { "events": [{"signal": "brush_seconds_date"}], - "update": "brush_seconds_date ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"seconds_date\", extent: brush_seconds_date}]} : null" + "update": "brush_seconds_date ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_seconds_date]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"seconds_date\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -290,7 +295,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "value": "goldenrod" }, {"value": "steelblue"} diff --git a/examples/compiled/selection_composition_and.vg.json b/examples/compiled/selection_composition_and.vg.json index b441b1e318..fd5b39f5c8 100644 --- a/examples/compiled/selection_composition_and.vg.json +++ b/examples/compiled/selection_composition_and.vg.json @@ -39,6 +39,8 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "alex", "update": "vlSelectionResolve(\"alex_store\")"}, + {"name": "morgan", "update": "vlSelectionResolve(\"morgan_store\")"}, { "name": "alex_x", "value": [], @@ -154,10 +156,14 @@ "on": [ { "events": [{"signal": "alex_Cylinders"}, {"signal": "alex_Origin"}], - "update": "alex_Cylinders && alex_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: alex_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: alex_Origin}]} : null" + "update": "alex_Cylinders && alex_Origin ? {unit: \"\", fields: alex_tuple_fields, values: [alex_Cylinders, alex_Origin]} : null" } ] }, + { + "name": "alex_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "alex_translate_anchor", "value": {}, @@ -359,10 +365,14 @@ {"signal": "morgan_Cylinders"}, {"signal": "morgan_Origin"} ], - "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: morgan_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: morgan_Origin}]} : null" + "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", fields: morgan_tuple_fields, values: [morgan_Cylinders, morgan_Origin]} : null" } ] }, + { + "name": "morgan_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "morgan_translate_anchor", "value": {}, @@ -537,7 +547,7 @@ "value": null }, { - "test": "!(length(data(\"alex_store\")) || length(data(\"morgan_store\"))) || ((vlInterval(\"alex_store\", datum)) && (vlInterval(\"morgan_store\", datum)))", + "test": "!(length(data(\"alex_store\")) || length(data(\"morgan_store\"))) || ((vlSelectionTest(\"alex_store\", datum)) && (vlSelectionTest(\"morgan_store\", datum)))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_composition_or.vg.json b/examples/compiled/selection_composition_or.vg.json index ea29ce160b..92cbd54ddf 100644 --- a/examples/compiled/selection_composition_or.vg.json +++ b/examples/compiled/selection_composition_or.vg.json @@ -39,6 +39,8 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "alex", "update": "vlSelectionResolve(\"alex_store\")"}, + {"name": "morgan", "update": "vlSelectionResolve(\"morgan_store\")"}, { "name": "alex_x", "value": [], @@ -154,10 +156,14 @@ "on": [ { "events": [{"signal": "alex_Cylinders"}, {"signal": "alex_Origin"}], - "update": "alex_Cylinders && alex_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: alex_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: alex_Origin}]} : null" + "update": "alex_Cylinders && alex_Origin ? {unit: \"\", fields: alex_tuple_fields, values: [alex_Cylinders, alex_Origin]} : null" } ] }, + { + "name": "alex_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "alex_translate_anchor", "value": {}, @@ -359,10 +365,14 @@ {"signal": "morgan_Cylinders"}, {"signal": "morgan_Origin"} ], - "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: morgan_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: morgan_Origin}]} : null" + "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", fields: morgan_tuple_fields, values: [morgan_Cylinders, morgan_Origin]} : null" } ] }, + { + "name": "morgan_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "morgan_translate_anchor", "value": {}, @@ -537,7 +547,7 @@ "value": null }, { - "test": "!(length(data(\"alex_store\")) || length(data(\"morgan_store\"))) || ((vlInterval(\"alex_store\", datum)) || (vlInterval(\"morgan_store\", datum)))", + "test": "!(length(data(\"alex_store\")) || length(data(\"morgan_store\"))) || ((vlSelectionTest(\"alex_store\", datum)) || (vlSelectionTest(\"morgan_store\", datum)))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_concat.vg.json b/examples/compiled/selection_concat.vg.json index 81ad95bdf3..cf6133bc96 100644 --- a/examples/compiled/selection_concat.vg.json +++ b/examples/compiled/selection_concat.vg.json @@ -30,6 +30,11 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, + { + "name": "grid", + "update": "{Displacement: grid_Displacement, Acceleration: grid_Acceleration}" + }, {"name": "grid_Displacement"}, {"name": "grid_Acceleration"} ], @@ -173,10 +178,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -473,10 +482,14 @@ {"signal": "grid_Displacement"}, {"signal": "grid_Acceleration"} ], - "update": "grid_Displacement && grid_Acceleration ? {unit: \"concat_1\", intervals: [{encoding: \"x\", field: \"Displacement\", extent: grid_Displacement}, {encoding: \"y\", field: \"Acceleration\", extent: grid_Acceleration}]} : null" + "update": "grid_Displacement && grid_Acceleration ? {unit: \"concat_1\", fields: grid_tuple_fields, values: [grid_Displacement, grid_Acceleration]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Displacement\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -559,7 +572,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "value": "steelblue" }, {"value": "red"} @@ -643,7 +656,7 @@ "name": "concat_1_x", "type": "linear", "domain": {"data": "source_0", "field": "Displacement"}, - "domainRaw": {"signal": "grid_Displacement"}, + "domainRaw": {"signal": "grid[\"Displacement\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -652,7 +665,7 @@ "name": "concat_1_y", "type": "linear", "domain": {"data": "source_0", "field": "Acceleration"}, - "domainRaw": {"signal": "grid_Acceleration"}, + "domainRaw": {"signal": "grid[\"Acceleration\"]"}, "range": [{"signal": "concat_1_height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/selection_filter.vg.json b/examples/compiled/selection_filter.vg.json index 989ddea324..21200bbffe 100644 --- a/examples/compiled/selection_filter.vg.json +++ b/examples/compiled/selection_filter.vg.json @@ -24,7 +24,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" } ] } @@ -38,7 +38,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -180,10 +181,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, diff --git a/examples/compiled/selection_filter_composition.vg.json b/examples/compiled/selection_filter_composition.vg.json index f5d52a53ee..01f460da18 100644 --- a/examples/compiled/selection_filter_composition.vg.json +++ b/examples/compiled/selection_filter_composition.vg.json @@ -24,7 +24,7 @@ "transform": [ { "type": "filter", - "expr": "(datum.Weight_in_lbs > 3000) && (!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum)))" + "expr": "(datum.Weight_in_lbs > 3000) && (!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum)))" } ] } @@ -38,7 +38,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -180,10 +181,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"concat_0\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"concat_0\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, diff --git a/examples/compiled/selection_insert.vg.json b/examples/compiled/selection_insert.vg.json index 43f5710217..ab2717f451 100644 --- a/examples/compiled/selection_insert.vg.json +++ b/examples/compiled/selection_insert.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_modify", "on": [ @@ -61,7 +69,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/selection_interval_mark_style.vg.json b/examples/compiled/selection_interval_mark_style.vg.json index 386b3cd360..8f45fc6c07 100644 --- a/examples/compiled/selection_interval_mark_style.vg.json +++ b/examples/compiled/selection_interval_mark_style.vg.json @@ -39,6 +39,8 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "alex", "update": "vlSelectionResolve(\"alex_store\")"}, + {"name": "morgan", "update": "vlSelectionResolve(\"morgan_store\")"}, { "name": "alex_x", "value": [], @@ -154,10 +156,14 @@ "on": [ { "events": [{"signal": "alex_Cylinders"}, {"signal": "alex_Origin"}], - "update": "alex_Cylinders && alex_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: alex_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: alex_Origin}]} : null" + "update": "alex_Cylinders && alex_Origin ? {unit: \"\", fields: alex_tuple_fields, values: [alex_Cylinders, alex_Origin]} : null" } ] }, + { + "name": "alex_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "alex_translate_anchor", "value": {}, @@ -359,10 +365,14 @@ {"signal": "morgan_Cylinders"}, {"signal": "morgan_Origin"} ], - "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: morgan_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: morgan_Origin}]} : null" + "update": "morgan_Cylinders && morgan_Origin ? {unit: \"\", fields: morgan_tuple_fields, values: [morgan_Cylinders, morgan_Origin]} : null" } ] }, + { + "name": "morgan_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "morgan_translate_anchor", "value": {}, diff --git a/examples/compiled/selection_layer_bar_month.vg.json b/examples/compiled/selection_layer_bar_month.vg.json index 0634824866..a59234674c 100644 --- a/examples/compiled/selection_layer_bar_month.vg.json +++ b/examples/compiled/selection_layer_bar_month.vg.json @@ -40,7 +40,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -65,6 +65,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -126,10 +127,14 @@ "on": [ { "events": [{"signal": "brush_month_date"}], - "update": "brush_month_date ? {unit: \"layer_0\", intervals: [{encoding: \"x\", field: \"month_date\", extent: brush_month_date}]} : null" + "update": "brush_month_date ? {unit: \"layer_0\", fields: brush_tuple_fields, values: [brush_month_date]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"month_date\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -264,7 +269,7 @@ ], "opacity": [ { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "value": 1 }, {"value": 0.7} diff --git a/examples/compiled/selection_multi_condition.vg.json b/examples/compiled/selection_multi_condition.vg.json index 476d4f2e2a..29dae657d8 100644 --- a/examples/compiled/selection_multi_condition.vg.json +++ b/examples/compiled/selection_multi_condition.vg.json @@ -27,6 +27,11 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, + { + "name": "hoverbrush", + "update": "vlSelectionResolve(\"hoverbrush_store\")" + }, { "name": "brush_x", "value": [], @@ -149,10 +154,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -237,11 +246,15 @@ "on": [ { "events": [{"source": "scope", "type": "mouseover"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: hoverbrush_tuple_fields, values: [(item().isVoronoi ? datum.datum : datum)[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "hoverbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "hoverbrush_toggle", "value": false, @@ -322,11 +335,11 @@ "value": null }, { - "test": "!(length(data(\"hoverbrush_store\"))) || (vlMulti(\"hoverbrush_store\", datum))", + "test": "!(length(data(\"hoverbrush_store\"))) || (vlSelectionTest(\"hoverbrush_store\", datum))", "value": "blue" }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "value": "skyblue" }, {"value": "grey"} diff --git a/examples/compiled/selection_project_binned_interval.vg.json b/examples/compiled/selection_project_binned_interval.vg.json index 91eb748e35..f055eff452 100644 --- a/examples/compiled/selection_project_binned_interval.vg.json +++ b/examples/compiled/selection_project_binned_interval.vg.json @@ -66,7 +66,7 @@ }, { "type": "filter", - "expr": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))" + "expr": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))" }, { "type": "aggregate", @@ -89,6 +89,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -153,10 +154,14 @@ "on": [ { "events": [{"signal": "brush_Acceleration"}], - "update": "brush_Acceleration ? {unit: \"layer_0\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Acceleration ? {unit: \"layer_0\", fields: brush_tuple_fields, values: [brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, diff --git a/examples/compiled/selection_project_interval.vg.json b/examples/compiled/selection_project_interval.vg.json index fd891288ec..299ccde655 100644 --- a/examples/compiled/selection_project_interval.vg.json +++ b/examples/compiled/selection_project_interval.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_x", "value": [], @@ -147,10 +148,14 @@ "on": [ { "events": [{"signal": "pts_Cylinders"}, {"signal": "pts_Origin"}], - "update": "pts_Cylinders && pts_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: pts_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: pts_Origin}]} : null" + "update": "pts_Cylinders && pts_Origin ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Cylinders, pts_Origin]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -282,7 +287,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlInterval(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_project_interval_x.vg.json b/examples/compiled/selection_project_interval_x.vg.json index 9b4b0e4716..d6347ee816 100644 --- a/examples/compiled/selection_project_interval_x.vg.json +++ b/examples/compiled/selection_project_interval_x.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_x", "value": [], @@ -97,10 +98,14 @@ "on": [ { "events": [{"signal": "pts_Cylinders"}], - "update": "pts_Cylinders ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: pts_Cylinders}]} : null" + "update": "pts_Cylinders ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Cylinders]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -232,7 +237,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlInterval(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_project_interval_x_y.vg.json b/examples/compiled/selection_project_interval_x_y.vg.json index fd891288ec..299ccde655 100644 --- a/examples/compiled/selection_project_interval_x_y.vg.json +++ b/examples/compiled/selection_project_interval_x_y.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_x", "value": [], @@ -147,10 +148,14 @@ "on": [ { "events": [{"signal": "pts_Cylinders"}, {"signal": "pts_Origin"}], - "update": "pts_Cylinders && pts_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: pts_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: pts_Origin}]} : null" + "update": "pts_Cylinders && pts_Origin ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Cylinders, pts_Origin]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -282,7 +287,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlInterval(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_project_interval_y.vg.json b/examples/compiled/selection_project_interval_y.vg.json index dfd723efcc..c98cd444d9 100644 --- a/examples/compiled/selection_project_interval_y.vg.json +++ b/examples/compiled/selection_project_interval_y.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_y", "value": [], @@ -97,10 +98,14 @@ "on": [ { "events": [{"signal": "pts_Origin"}], - "update": "pts_Origin ? {unit: \"\", intervals: [{encoding: \"y\", field: \"Origin\", extent: pts_Origin}]} : null" + "update": "pts_Origin ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Origin]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -232,7 +237,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlInterval(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_project_multi.vg.json b/examples/compiled/selection_project_multi.vg.json index b38d108f49..41fd51e837 100644 --- a/examples/compiled/selection_project_multi.vg.json +++ b/examples/compiled/selection_project_multi.vg.json @@ -25,17 +25,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -78,7 +83,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -91,7 +96,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} diff --git a/examples/compiled/selection_project_multi_cylinders.vg.json b/examples/compiled/selection_project_multi_cylinders.vg.json index 55c3dc3759..8daa7f6606 100644 --- a/examples/compiled/selection_project_multi_cylinders.vg.json +++ b/examples/compiled/selection_project_multi_cylinders.vg.json @@ -24,17 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Cylinders\"], values: [datum[\"Cylinders\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Cylinders\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -77,7 +82,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -90,7 +95,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} diff --git a/examples/compiled/selection_project_multi_cylinders_origin.vg.json b/examples/compiled/selection_project_multi_cylinders_origin.vg.json index 67b2da3dc8..13a2617ec5 100644 --- a/examples/compiled/selection_project_multi_cylinders_origin.vg.json +++ b/examples/compiled/selection_project_multi_cylinders_origin.vg.json @@ -24,17 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Cylinders\", \"Origin\"], values: [datum[\"Cylinders\"], datum[\"Origin\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Cylinders\"], datum[\"Origin\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"},{\"field\":\"Origin\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -77,7 +82,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -90,14 +95,14 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} ], "shape": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "shape", "field": "Origin" }, diff --git a/examples/compiled/selection_project_multi_origin.vg.json b/examples/compiled/selection_project_multi_origin.vg.json index 94833029c5..f6b997af7c 100644 --- a/examples/compiled/selection_project_multi_origin.vg.json +++ b/examples/compiled/selection_project_multi_origin.vg.json @@ -24,17 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Origin\"], values: [datum[\"Origin\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Origin\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Origin\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -77,7 +82,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -90,14 +95,14 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} ], "shape": [ { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "shape", "field": "Origin" }, diff --git a/examples/compiled/selection_project_single.vg.json b/examples/compiled/selection_project_single.vg.json index 2b5d046841..973e8161d0 100644 --- a/examples/compiled/selection_project_single.vg.json +++ b/examples/compiled/selection_project_single.vg.json @@ -25,21 +25,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {_vgsid_: data(\"pts_store\")[0].values[0]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -72,7 +73,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -85,7 +86,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} diff --git a/examples/compiled/selection_project_single_cylinders.vg.json b/examples/compiled/selection_project_single_cylinders.vg.json index d35ec611ec..158b7a7c61 100644 --- a/examples/compiled/selection_project_single_cylinders.vg.json +++ b/examples/compiled/selection_project_single_cylinders.vg.json @@ -24,21 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {Cylinders: data(\"pts_store\")[0].values[0]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Cylinders\"], values: [datum[\"Cylinders\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Cylinders\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -71,7 +72,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -84,7 +85,7 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} diff --git a/examples/compiled/selection_project_single_cylinders_origin.vg.json b/examples/compiled/selection_project_single_cylinders_origin.vg.json index 6d99fe510d..257a3961ef 100644 --- a/examples/compiled/selection_project_single_cylinders_origin.vg.json +++ b/examples/compiled/selection_project_single_cylinders_origin.vg.json @@ -24,21 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {Cylinders: data(\"pts_store\")[0].values[0], Origin: data(\"pts_store\")[0].values[1]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Cylinders\", \"Origin\"], values: [datum[\"Cylinders\"], datum[\"Origin\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Cylinders\"], datum[\"Origin\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"type\":\"E\"},{\"field\":\"Origin\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -71,7 +72,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -84,14 +85,14 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} ], "shape": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "shape", "field": "Origin" }, diff --git a/examples/compiled/selection_project_single_origin.vg.json b/examples/compiled/selection_project_single_origin.vg.json index a9a82515c9..544266c719 100644 --- a/examples/compiled/selection_project_single_origin.vg.json +++ b/examples/compiled/selection_project_single_origin.vg.json @@ -24,21 +24,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {Origin: data(\"pts_store\")[0].values[0]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"Origin\"], values: [datum[\"Origin\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"Origin\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Origin\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -71,7 +72,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "Cylinders" }, @@ -84,14 +85,14 @@ "y": {"scale": "y", "field": "Miles_per_Gallon"}, "size": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": 200 }, {"value": 50} ], "shape": [ { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "shape", "field": "Origin" }, diff --git a/examples/compiled/selection_resolution_global.vg.json b/examples/compiled/selection_resolution_global.vg.json index 0941be47a2..06d7164444 100644 --- a/examples/compiled/selection_resolution_global.vg.json +++ b/examples/compiled/selection_resolution_global.vg.json @@ -26,7 +26,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -165,10 +166,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -315,7 +320,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -559,10 +564,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -709,7 +718,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -832,7 +841,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -843,7 +852,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -861,19 +870,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[1])]" + "update": "[scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -881,24 +890,28 @@ "name": "brush_Horsepower", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Horsepower_Horsepower_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Horsepower_Horsepower_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_y\", brush_y)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_y\", brush_y)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_x\", brush_x)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_x\", brush_x)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Horsepower"}], - "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -911,7 +924,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -996,28 +1009,28 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ] @@ -1045,7 +1058,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -1075,33 +1088,33 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Horsepower_Horsepower\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ], "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1286,10 +1299,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1436,7 +1453,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -1559,7 +1576,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -1570,7 +1587,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -1588,19 +1605,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[1])]" + "update": "[scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -1608,24 +1625,28 @@ "name": "brush_Acceleration", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Acceleration_Acceleration_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Acceleration_Acceleration_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_y\", brush_y)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_y\", brush_y)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_x\", brush_x)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_x\", brush_x)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Acceleration"}], - "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1638,7 +1659,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -1723,28 +1744,28 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ] @@ -1772,7 +1793,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -1802,33 +1823,33 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Acceleration_Acceleration\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ], "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -2013,10 +2034,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2163,7 +2188,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -2286,7 +2311,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -2297,7 +2322,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -2315,19 +2340,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[1])]" + "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -2335,24 +2360,28 @@ "name": "brush_Miles_per_Gallon", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Miles_per_Gallon"}], - "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2365,7 +2394,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -2450,28 +2479,28 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ] @@ -2499,7 +2528,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -2529,33 +2558,33 @@ "x": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "value": 0 + "signal": "brush_x[0]" }, {"value": 0} ], "y": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "signal": "brush_y[0]" + "value": 0 }, {"value": 0} ], "x2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "field": {"group": "width"} + "signal": "brush_x[1]" }, {"value": 0} ], "y2": [ { "test": "data(\"brush_store\").length && data(\"brush_store\")[0].unit === \"child_Miles_per_Gallon_Miles_per_Gallon\"", - "signal": "brush_y[1]" + "field": {"group": "height"} }, {"value": 0} ], "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -2740,10 +2769,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2890,7 +2923,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, @@ -3134,10 +3167,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -3284,7 +3321,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_resolution_intersect.svg b/examples/compiled/selection_resolution_intersect.svg index 50f4caec5f..9a7f7fe583 100644 --- a/examples/compiled/selection_resolution_intersect.svg +++ b/examples/compiled/selection_resolution_intersect.svg @@ -1 +1 @@ -01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file +01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file diff --git a/examples/compiled/selection_resolution_intersect.vg.json b/examples/compiled/selection_resolution_intersect.vg.json index be3471d11b..68deb40f9d 100644 --- a/examples/compiled/selection_resolution_intersect.vg.json +++ b/examples/compiled/selection_resolution_intersect.vg.json @@ -26,6 +26,10 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] + }, + { + "name": "brush", + "update": "vlSelectionResolve(\"brush_store\", \"intersect\")" } ], "layout": { @@ -165,10 +169,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -291,7 +299,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -511,10 +519,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -637,7 +649,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -736,7 +748,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -747,7 +759,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -765,19 +777,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[1])]" + "update": "[scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -785,24 +797,28 @@ "name": "brush_Horsepower", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Horsepower_Horsepower_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Horsepower_Horsepower_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_y\", brush_y)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_y\", brush_y)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_x\", brush_x)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_x\", brush_x)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Horsepower"}], - "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -815,7 +831,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -897,10 +913,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -925,7 +941,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -952,12 +968,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1142,10 +1158,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1268,7 +1288,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -1367,7 +1387,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -1378,7 +1398,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -1396,19 +1416,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[1])]" + "update": "[scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -1416,24 +1436,28 @@ "name": "brush_Acceleration", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Acceleration_Acceleration_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Acceleration_Acceleration_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_y\", brush_y)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_y\", brush_y)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_x\", brush_x)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_x\", brush_x)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Acceleration"}], - "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1446,7 +1470,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -1528,10 +1552,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -1556,7 +1580,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -1583,12 +1607,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1773,10 +1797,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1899,7 +1927,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -1998,7 +2026,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -2009,7 +2037,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -2027,19 +2055,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[1])]" + "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -2047,24 +2075,28 @@ "name": "brush_Miles_per_Gallon", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Miles_per_Gallon"}], - "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2077,7 +2109,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -2159,10 +2191,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -2187,7 +2219,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -2214,12 +2246,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -2404,10 +2436,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2530,7 +2566,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, @@ -2750,10 +2786,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2876,7 +2916,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_resolution_union.svg b/examples/compiled/selection_resolution_union.svg index 50f4caec5f..9a7f7fe583 100644 --- a/examples/compiled/selection_resolution_union.svg +++ b/examples/compiled/selection_resolution_union.svg @@ -1 +1 @@ -01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file +01020304050Miles_per_Gallon050100150200Horsepower0510152025Acceleration050100150200Horsepower050100150200Horsepower050100150200Horsepower01020304050Miles_per_Gallon0510152025Acceleration0510152025Acceleration0510152025Acceleration050100150200Horsepower0510152025Acceleration01020304050Miles_per_Gallon01020304050Miles_per_Gallon0510152025Acceleration01020304050Miles_per_Gallon050100150200Horsepower01020304050Miles_per_GallonEuropeJapanUSAOrigin \ No newline at end of file diff --git a/examples/compiled/selection_resolution_union.vg.json b/examples/compiled/selection_resolution_union.vg.json index 7e7abd63f2..fdd689ffdd 100644 --- a/examples/compiled/selection_resolution_union.vg.json +++ b/examples/compiled/selection_resolution_union.vg.json @@ -26,6 +26,10 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] + }, + { + "name": "brush", + "update": "vlSelectionResolve(\"brush_store\", \"union\")" } ], "layout": { @@ -165,10 +169,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Miles_per_Gallon && brush_Horsepower ? {unit: \"child_Horsepower_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -291,7 +299,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -511,10 +519,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Horsepower"} ], - "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Acceleration && brush_Horsepower ? {unit: \"child_Horsepower_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Horsepower\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -637,7 +649,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -736,7 +748,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -747,7 +759,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -765,19 +777,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_y\", brush_Horsepower[1])]" + "update": "[scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[0]), scale(\"child_Horsepower_Horsepower_x\", brush_Horsepower[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -785,24 +797,28 @@ "name": "brush_Horsepower", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Horsepower_Horsepower_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Horsepower_Horsepower_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_y\", brush_y)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_y\", brush_y)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Horsepower) || (+invert(\"child_Horsepower_Horsepower_x\", brush_x)[0] === +brush_Horsepower[0] && +invert(\"child_Horsepower_Horsepower_x\", brush_x)[1] === +brush_Horsepower[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Horsepower"}], - "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", intervals: [{encoding: \"y\", field: \"Horsepower\", extent: brush_Horsepower}]} : null" + "update": "brush_Horsepower ? {unit: \"child_Horsepower_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -815,7 +831,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -897,10 +913,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -925,7 +941,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -952,12 +968,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1142,10 +1158,14 @@ {"signal": "brush_Miles_per_Gallon"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", intervals: [{encoding: \"x\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Miles_per_Gallon && brush_Acceleration ? {unit: \"child_Acceleration_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1268,7 +1288,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1367,7 +1387,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -1378,7 +1398,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -1396,19 +1416,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_y\", brush_Acceleration[1])]" + "update": "[scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[0]), scale(\"child_Acceleration_Acceleration_x\", brush_Acceleration[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -1416,24 +1436,28 @@ "name": "brush_Acceleration", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Acceleration_Acceleration_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Acceleration_Acceleration_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_y\", brush_y)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_y\", brush_y)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Acceleration) || (+invert(\"child_Acceleration_Acceleration_x\", brush_x)[0] === +brush_Acceleration[0] && +invert(\"child_Acceleration_Acceleration_x\", brush_x)[1] === +brush_Acceleration[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Acceleration"}], - "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", intervals: [{encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Acceleration ? {unit: \"child_Acceleration_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1446,7 +1470,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -1528,10 +1552,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -1556,7 +1580,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1583,12 +1607,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -1773,10 +1797,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Acceleration"} ], - "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Acceleration\", extent: brush_Acceleration}]} : null" + "update": "brush_Horsepower && brush_Acceleration ? {unit: \"child_Acceleration_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Acceleration]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Acceleration\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -1899,7 +1927,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -1998,7 +2026,7 @@ }, "signals": [ { - "name": "brush_y", + "name": "brush_x", "value": [], "on": [ { @@ -2009,7 +2037,7 @@ "!event.item || event.item.mark.name !== \"brush_brush\"" ] }, - "update": "[y(unit), y(unit)]" + "update": "[x(unit), x(unit)]" }, { "events": { @@ -2027,19 +2055,19 @@ {"source": "window", "type": "mouseup"} ] }, - "update": "[brush_y[0], clamp(y(unit), 0, height)]" + "update": "[brush_x[0], clamp(x(unit), 0, width)]" }, { "events": {"signal": "brush_scale_trigger"}, - "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_Miles_per_Gallon[1])]" + "update": "[scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[0]), scale(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_Miles_per_Gallon[1])]" }, { "events": {"signal": "brush_translate_delta"}, - "update": "clampRange(panLinear(brush_translate_anchor.extent_y, brush_translate_delta.y / span(brush_translate_anchor.extent_y)), 0, height)" + "update": "clampRange(panLinear(brush_translate_anchor.extent_x, brush_translate_delta.x / span(brush_translate_anchor.extent_x)), 0, width)" }, { "events": {"signal": "brush_zoom_delta"}, - "update": "clampRange(zoomLinear(brush_y, brush_zoom_anchor.y, brush_zoom_delta), 0, height)" + "update": "clampRange(zoomLinear(brush_x, brush_zoom_anchor.x, brush_zoom_delta), 0, width)" } ] }, @@ -2047,24 +2075,28 @@ "name": "brush_Miles_per_Gallon", "on": [ { - "events": {"signal": "brush_y"}, - "update": "brush_y[0] === brush_y[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)" + "events": {"signal": "brush_x"}, + "update": "brush_x[0] === brush_x[1] ? null : invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)" } ] }, { "name": "brush_scale_trigger", - "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_y\", brush_y)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" + "update": "(!isArray(brush_Miles_per_Gallon) || (+invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[0] === +brush_Miles_per_Gallon[0] && +invert(\"child_Miles_per_Gallon_Miles_per_Gallon_x\", brush_x)[1] === +brush_Miles_per_Gallon[1])) ? brush_scale_trigger : {}" }, { "name": "brush_tuple", "on": [ { "events": [{"signal": "brush_Miles_per_Gallon"}], - "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", intervals: [{encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Miles_per_Gallon\", fields: brush_tuple_fields, values: [brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Miles_per_Gallon\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2077,7 +2109,7 @@ "markname": "brush_brush" } ], - "update": "{x: x(unit), y: y(unit), extent_y: slice(brush_y)}" + "update": "{x: x(unit), y: y(unit), extent_x: slice(brush_x)}" } ] }, @@ -2159,10 +2191,10 @@ "fillOpacity": {"value": 0.125} }, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"} + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}} } } }, @@ -2187,7 +2219,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -2214,12 +2246,12 @@ "encode": { "enter": {"fill": {"value": "transparent"}}, "update": { - "x": {"value": 0}, - "y": {"signal": "brush_y[0]"}, - "x2": {"field": {"group": "width"}}, - "y2": {"signal": "brush_y[1]"}, + "x": {"signal": "brush_x[0]"}, + "y": {"value": 0}, + "x2": {"signal": "brush_x[1]"}, + "y2": {"field": {"group": "height"}}, "stroke": [ - {"test": "brush_y[0] !== brush_y[1]", "value": "white"}, + {"test": "brush_x[0] !== brush_x[1]", "value": "white"}, {"value": null} ] } @@ -2404,10 +2436,14 @@ {"signal": "brush_Acceleration"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", intervals: [{encoding: \"x\", field: \"Acceleration\", extent: brush_Acceleration}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Acceleration && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Acceleration\", fields: brush_tuple_fields, values: [brush_Acceleration, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Acceleration\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2530,7 +2566,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, @@ -2750,10 +2786,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"child_Miles_per_Gallon_Horsepower\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -2876,7 +2916,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"union\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"union\"))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_toggle_altKey.vg.json b/examples/compiled/selection_toggle_altKey.vg.json index 5d9ee98888..0cca4e6f6a 100644 --- a/examples/compiled/selection_toggle_altKey.vg.json +++ b/examples/compiled/selection_toggle_altKey.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -71,7 +79,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/selection_toggle_altKey_shiftKey.vg.json b/examples/compiled/selection_toggle_altKey_shiftKey.vg.json index e9cf560d3d..871cafebe3 100644 --- a/examples/compiled/selection_toggle_altKey_shiftKey.vg.json +++ b/examples/compiled/selection_toggle_altKey_shiftKey.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -71,7 +79,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/selection_toggle_shiftKey.vg.json b/examples/compiled/selection_toggle_shiftKey.vg.json index a31033cdf5..55e78f8066 100644 --- a/examples/compiled/selection_toggle_shiftKey.vg.json +++ b/examples/compiled/selection_toggle_shiftKey.vg.json @@ -25,17 +25,25 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + { + "name": "paintbrush", + "update": "vlSelectionResolve(\"paintbrush_store\")" + }, { "name": "paintbrush_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: paintbrush_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "paintbrush_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "paintbrush_toggle", "value": false, @@ -71,7 +79,7 @@ "value": null }, { - "test": "!(length(data(\"paintbrush_store\"))) || (vlMulti(\"paintbrush_store\", datum))", + "test": "!(length(data(\"paintbrush_store\"))) || (vlSelectionTest(\"paintbrush_store\", datum))", "scale": "color", "field": "Cylinders" }, diff --git a/examples/compiled/selection_translate_brush_drag.vg.json b/examples/compiled/selection_translate_brush_drag.vg.json index a71aef5a1a..8103dc78a7 100644 --- a/examples/compiled/selection_translate_brush_drag.vg.json +++ b/examples/compiled/selection_translate_brush_drag.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -150,10 +151,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -287,7 +292,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_translate_brush_shift-drag.vg.json b/examples/compiled/selection_translate_brush_shift-drag.vg.json index 86ad741173..e9ad5acaa4 100644 --- a/examples/compiled/selection_translate_brush_shift-drag.vg.json +++ b/examples/compiled/selection_translate_brush_shift-drag.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -150,10 +151,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -293,7 +298,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_translate_scatterplot_drag.vg.json b/examples/compiled/selection_translate_scatterplot_drag.vg.json index 3707162e9a..5d5358c6c7 100644 --- a/examples/compiled/selection_translate_scatterplot_drag.vg.json +++ b/examples/compiled/selection_translate_scatterplot_drag.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "grid", "update": "vlSelectionResolve(\"grid_store\")"}, { "name": "grid_Horsepower", "on": [ @@ -62,10 +63,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -158,7 +163,7 @@ "name": "x", "type": "linear", "domain": [75, 150], - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": false @@ -167,7 +172,7 @@ "name": "y", "type": "linear", "domain": [20, 40], - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": false diff --git a/examples/compiled/selection_translate_scatterplot_shift-drag.vg.json b/examples/compiled/selection_translate_scatterplot_shift-drag.vg.json index a658471cc6..eb55dc9308 100644 --- a/examples/compiled/selection_translate_scatterplot_shift-drag.vg.json +++ b/examples/compiled/selection_translate_scatterplot_shift-drag.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "grid", "update": "vlSelectionResolve(\"grid_store\")"}, { "name": "grid_Horsepower", "on": [ @@ -62,10 +63,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -168,7 +173,7 @@ "name": "x", "type": "linear", "domain": [75, 150], - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": false @@ -177,7 +182,7 @@ "name": "y", "type": "linear", "domain": [20, 40], - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": false diff --git a/examples/compiled/selection_type_interval.vg.json b/examples/compiled/selection_type_interval.vg.json index fd891288ec..299ccde655 100644 --- a/examples/compiled/selection_type_interval.vg.json +++ b/examples/compiled/selection_type_interval.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_x", "value": [], @@ -147,10 +148,14 @@ "on": [ { "events": [{"signal": "pts_Cylinders"}, {"signal": "pts_Origin"}], - "update": "pts_Cylinders && pts_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: pts_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: pts_Origin}]} : null" + "update": "pts_Cylinders && pts_Origin ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Cylinders, pts_Origin]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -282,7 +287,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlInterval(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_type_interval_invert.vg.json b/examples/compiled/selection_type_interval_invert.vg.json index 23f670121b..7fb0f0297b 100644 --- a/examples/compiled/selection_type_interval_invert.vg.json +++ b/examples/compiled/selection_type_interval_invert.vg.json @@ -38,6 +38,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_x", "value": [], @@ -147,10 +148,14 @@ "on": [ { "events": [{"signal": "pts_Cylinders"}, {"signal": "pts_Origin"}], - "update": "pts_Cylinders && pts_Origin ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Cylinders\", extent: pts_Cylinders}, {encoding: \"y\", field: \"Origin\", extent: pts_Origin}]} : null" + "update": "pts_Cylinders && pts_Origin ? {unit: \"\", fields: pts_tuple_fields, values: [pts_Cylinders, pts_Origin]} : null" } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"Cylinders\",\"channel\":\"x\",\"type\":\"E\"},{\"field\":\"Origin\",\"channel\":\"y\",\"type\":\"E\"}]" + }, { "name": "pts_translate_anchor", "value": {}, @@ -282,7 +287,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (!(vlInterval(\"pts_store\", datum)))", + "test": "!(length(data(\"pts_store\"))) || (!(vlSelectionTest(\"pts_store\", datum)))", "value": "grey" }, {"scale": "color", "field": "count_*"} diff --git a/examples/compiled/selection_type_multi.vg.json b/examples/compiled/selection_type_multi.vg.json index df3de61115..76bef45573 100644 --- a/examples/compiled/selection_type_multi.vg.json +++ b/examples/compiled/selection_type_multi.vg.json @@ -40,17 +40,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -85,7 +90,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_type_single.vg.json b/examples/compiled/selection_type_single.vg.json index 8483026570..ed70fe2048 100644 --- a/examples/compiled/selection_type_single.vg.json +++ b/examples/compiled/selection_type_single.vg.json @@ -40,21 +40,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {_vgsid_: data(\"pts_store\")[0].values[0]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -79,7 +80,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_type_single_dblclick.vg.json b/examples/compiled/selection_type_single_dblclick.vg.json index 54e81d15de..e20dcb598a 100644 --- a/examples/compiled/selection_type_single_dblclick.vg.json +++ b/examples/compiled/selection_type_single_dblclick.vg.json @@ -40,21 +40,22 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, - { - "name": "pts", - "update": "data(\"pts_store\").length && {_vgsid_: data(\"pts_store\")[0].values[0]}" - }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"}, { "name": "pts_tuple", "value": {}, "on": [ { "events": [{"source": "scope", "type": "dblclick"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", encodings: [], fields: [\"_vgsid_\"], values: [datum[\"_vgsid_\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"\", fields: pts_tuple_fields, values: [datum[\"_vgsid_\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"_vgsid_\",\"type\":\"E\"}]" + }, { "name": "pts_modify", "on": [ @@ -79,7 +80,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlSingle(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "scale": "color", "field": "count_*" }, diff --git a/examples/compiled/selection_zoom_brush_shift-wheel.vg.json b/examples/compiled/selection_zoom_brush_shift-wheel.vg.json index 2e7f7ad7a3..11a4145d12 100644 --- a/examples/compiled/selection_zoom_brush_shift-wheel.vg.json +++ b/examples/compiled/selection_zoom_brush_shift-wheel.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -150,10 +151,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -289,7 +294,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_zoom_brush_wheel.vg.json b/examples/compiled/selection_zoom_brush_wheel.vg.json index a71aef5a1a..8103dc78a7 100644 --- a/examples/compiled/selection_zoom_brush_wheel.vg.json +++ b/examples/compiled/selection_zoom_brush_wheel.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "brush", "update": "vlSelectionResolve(\"brush_store\")"}, { "name": "brush_x", "value": [], @@ -150,10 +151,14 @@ {"signal": "brush_Horsepower"}, {"signal": "brush_Miles_per_Gallon"} ], - "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: brush_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: brush_Miles_per_Gallon}]} : null" + "update": "brush_Horsepower && brush_Miles_per_Gallon ? {unit: \"\", fields: brush_tuple_fields, values: [brush_Horsepower, brush_Miles_per_Gallon]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -287,7 +292,7 @@ "value": null }, { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum))", "scale": "color", "field": "Origin" }, diff --git a/examples/compiled/selection_zoom_scatterplot_shift-wheel.vg.json b/examples/compiled/selection_zoom_scatterplot_shift-wheel.vg.json index 1b04610f35..b8f3913fe5 100644 --- a/examples/compiled/selection_zoom_scatterplot_shift-wheel.vg.json +++ b/examples/compiled/selection_zoom_scatterplot_shift-wheel.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "grid", "update": "vlSelectionResolve(\"grid_store\")"}, { "name": "grid_Horsepower", "on": [ @@ -62,10 +63,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -172,7 +177,7 @@ "name": "x", "type": "linear", "domain": [75, 150], - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": false @@ -181,7 +186,7 @@ "name": "y", "type": "linear", "domain": [20, 40], - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": false diff --git a/examples/compiled/selection_zoom_scatterplot_wheel.vg.json b/examples/compiled/selection_zoom_scatterplot_wheel.vg.json index 3707162e9a..5d5358c6c7 100644 --- a/examples/compiled/selection_zoom_scatterplot_wheel.vg.json +++ b/examples/compiled/selection_zoom_scatterplot_wheel.vg.json @@ -28,6 +28,7 @@ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] }, + {"name": "grid", "update": "vlSelectionResolve(\"grid_store\")"}, { "name": "grid_Horsepower", "on": [ @@ -62,10 +63,14 @@ {"signal": "grid_Horsepower"}, {"signal": "grid_Miles_per_Gallon"} ], - "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", intervals: [{encoding: \"x\", field: \"Horsepower\", extent: grid_Horsepower}, {encoding: \"y\", field: \"Miles_per_Gallon\", extent: grid_Miles_per_Gallon}]} : null" + "update": "grid_Horsepower && grid_Miles_per_Gallon ? {unit: \"\", fields: grid_tuple_fields, values: [grid_Horsepower, grid_Miles_per_Gallon]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"Horsepower\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Miles_per_Gallon\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -158,7 +163,7 @@ "name": "x", "type": "linear", "domain": [75, 150], - "domainRaw": {"signal": "grid_Horsepower"}, + "domainRaw": {"signal": "grid[\"Horsepower\"]"}, "range": [0, {"signal": "width"}], "nice": true, "zero": false @@ -167,7 +172,7 @@ "name": "y", "type": "linear", "domain": [20, 40], - "domainRaw": {"signal": "grid_Miles_per_Gallon"}, + "domainRaw": {"signal": "grid[\"Miles_per_Gallon\"]"}, "range": [{"signal": "height"}, 0], "nice": true, "zero": false diff --git a/examples/compiled/trellis_selections.vg.json b/examples/compiled/trellis_selections.vg.json index cd7b2125f8..d4f994d91c 100644 --- a/examples/compiled/trellis_selections.vg.json +++ b/examples/compiled/trellis_selections.vg.json @@ -39,12 +39,14 @@ ], "bind": {"input": "number"} }, + { + "name": "brush", + "update": "vlSelectionResolve(\"brush_store\", \"intersect\")" + }, + {"name": "grid", "update": "{X: grid_X, Y: grid_Y}"}, {"name": "grid_X"}, {"name": "grid_Y"}, - { - "name": "xenc", - "update": "data(\"xenc_store\").length && {X: data(\"xenc_store\")[0].values[0]}" - } + {"name": "xenc", "update": "vlSelectionResolve(\"xenc_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -201,10 +203,14 @@ "on": [ { "events": [{"signal": "brush_X"}], - "update": "brush_X ? {unit: \"child\" + '_' + (facet[\"Series\"]), intervals: [{encoding: \"x\", field: \"X\", extent: brush_X}]} : null" + "update": "brush_X ? {unit: \"child\" + '_' + (facet[\"Series\"]), fields: brush_tuple_fields, values: [brush_X]} : null" } ] }, + { + "name": "brush_tuple_fields", + "update": "[{\"field\":\"X\",\"channel\":\"x\",\"type\":\"R\"}]" + }, { "name": "brush_translate_anchor", "value": {}, @@ -321,10 +327,14 @@ "on": [ { "events": [{"signal": "grid_X"}, {"signal": "grid_Y"}], - "update": "grid_X && grid_Y ? {unit: \"child\" + '_' + (facet[\"Series\"]), intervals: [{encoding: \"x\", field: \"X\", extent: grid_X}, {encoding: \"y\", field: \"Y\", extent: grid_Y}]} : null" + "update": "grid_X && grid_Y ? {unit: \"child\" + '_' + (facet[\"Series\"]), fields: grid_tuple_fields, values: [grid_X, grid_Y]} : null" } ] }, + { + "name": "grid_tuple_fields", + "update": "[{\"field\":\"X\",\"channel\":\"x\",\"type\":\"R\"},{\"field\":\"Y\",\"channel\":\"y\",\"type\":\"R\"}]" + }, { "name": "grid_translate_anchor", "value": {}, @@ -394,7 +404,11 @@ }, { "name": "xenc_tuple", - "update": "xenc_X ? {fields: [\"X\"], values: [xenc_X]} : null" + "update": "xenc_X ? {fields: xenc_tuple_fields, values: [xenc_X]} : null" + }, + { + "name": "xenc_tuple_fields", + "update": "[{\"field\":\"X\",\"type\":\"E\"}]" }, { "name": "xenc_modify", @@ -439,7 +453,7 @@ "value": null }, { - "test": "!(length(data(\"xenc_store\"))) || (vlSingle(\"xenc_store\", datum))", + "test": "!(length(data(\"xenc_store\"))) || (vlSelectionTest(\"xenc_store\", datum))", "value": "red" }, {"value": "steelblue"} @@ -451,7 +465,7 @@ "y": {"scale": "y", "field": "Y"}, "size": [ { - "test": "!(length(data(\"brush_store\"))) || (vlInterval(\"brush_store\", datum, \"intersect\"))", + "test": "!(length(data(\"brush_store\"))) || (vlSelectionTest(\"brush_store\", datum, \"intersect\"))", "value": 250 }, {"value": 100} @@ -535,7 +549,7 @@ "name": "x", "type": "linear", "domain": {"data": "source_0", "field": "X"}, - "domainRaw": {"signal": "grid_X"}, + "domainRaw": {"signal": "grid[\"X\"]"}, "range": [0, {"signal": "child_width"}], "zero": false, "nice": true @@ -544,7 +558,7 @@ "name": "y", "type": "linear", "domain": {"data": "source_0", "field": "Y"}, - "domainRaw": {"signal": "grid_Y"}, + "domainRaw": {"signal": "grid[\"Y\"]"}, "range": [{"signal": "child_height"}, 0], "zero": false, "nice": true diff --git a/examples/compiled/vconcat_flatten.vg.json b/examples/compiled/vconcat_flatten.vg.json index 12a664ccdf..fc27a1efe4 100644 --- a/examples/compiled/vconcat_flatten.vg.json +++ b/examples/compiled/vconcat_flatten.vg.json @@ -67,7 +67,7 @@ "transform": [ { "type": "filter", - "expr": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))" + "expr": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))" } ] } @@ -81,7 +81,8 @@ "on": [ {"events": "mousemove", "update": "isTuple(group()) ? group() : unit"} ] - } + }, + {"name": "pts", "update": "vlSelectionResolve(\"pts_store\")"} ], "layout": { "padding": {"row": 10, "column": 10}, @@ -108,11 +109,15 @@ "on": [ { "events": [{"source": "scope", "type": "click"}], - "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_0\", encodings: [], fields: [\"id\"], values: [datum[\"id\"]]} : null", + "update": "datum && item().mark.marktype !== 'group' ? {unit: \"concat_0\", fields: pts_tuple_fields, values: [datum[\"id\"]]} : null", "force": true } ] }, + { + "name": "pts_tuple_fields", + "update": "[{\"field\":\"id\",\"type\":\"E\"}]" + }, { "name": "pts_toggle", "value": false, @@ -148,7 +153,7 @@ "value": null }, { - "test": "!(length(data(\"pts_store\"))) || (vlMulti(\"pts_store\", datum))", + "test": "!(length(data(\"pts_store\"))) || (vlSelectionTest(\"pts_store\", datum))", "value": "steelblue" }, {"value": "grey"} From 6745760fbb86a025b7fae5ed32eac15a1db34f33 Mon Sep 17 00:00:00 2001 From: Travis CI Date: Sat, 13 Oct 2018 18:21:06 +0000 Subject: [PATCH 14/14] [Travis] Auto-formatting (build: 19319) --- src/compile/selection/interval.ts | 23 +++++++++++---------- src/compile/selection/multi.ts | 21 +++++++++++-------- src/compile/selection/transforms/project.ts | 11 ++++++---- test/compile/selection/interval.test.ts | 3 +-- test/compile/selection/parse.test.ts | 8 +++++-- test/compile/selection/predicate.test.ts | 9 ++++++-- test/compile/selection/single.test.ts | 2 +- 7 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/compile/selection/interval.ts b/src/compile/selection/interval.ts index aa6dd9fcde..6aa56e1e2c 100644 --- a/src/compile/selection/interval.ts +++ b/src/compile/selection/interval.ts @@ -82,7 +82,8 @@ const interval: SelectionCompiler = { on: [ { events: dataSignals.map(t => ({signal: t})), - update: dataSignals.join(' && ') + + update: + dataSignals.join(' && ') + ` ? {unit: ${unitName(model)}, fields: ${fieldsSg}, ` + `values: [${dataSignals.join(', ')}]} : null` } @@ -208,16 +209,16 @@ function channelSignals(model: UnitModel, selCmpt: SelectionComponent, channel: return hasScales ? [{name: dname, on: []}] : [ - { - name: vname, - value: [], - on: on - }, - { - name: dname, - on: [{events: {signal: vname}, update: `${vname}[0] === ${vname}[1] ? null : invert(${scaleStr}, ${vname})`}] - } - ]; + { + name: vname, + value: [], + on: on + }, + { + name: dname, + on: [{events: {signal: vname}, update: `${vname}[0] === ${vname}[1] ? null : invert(${scaleStr}, ${vname})`}] + } + ]; } function events(selCmpt: SelectionComponent, cb: (...args: any[]) => void) { diff --git a/src/compile/selection/multi.ts b/src/compile/selection/multi.ts index e53564d617..16ceb57e32 100644 --- a/src/compile/selection/multi.ts +++ b/src/compile/selection/multi.ts @@ -9,14 +9,16 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { const fieldsSg = name + TUPLE + TUPLE_FIELDS; const proj = selCmpt.project; const datum = nearest.has(selCmpt) ? '(item().isVoronoi ? datum.datum : datum)' : 'datum'; - const values = proj.map(p => { - const fieldDef = model.fieldDef(p.channel); - // Binned fields should capture extents, for a range test against the raw field. - return fieldDef && fieldDef.bin - ? (`[${accessPathWithDatum(model.vgField(p.channel, {}), datum)}, ` + - `${accessPathWithDatum(model.vgField(p.channel, {binSuffix: 'end'}), datum)}]`) - : `${accessPathWithDatum(p.field, datum)}`; - }).join(', '); + const values = proj + .map(p => { + const fieldDef = model.fieldDef(p.channel); + // Binned fields should capture extents, for a range test against the raw field. + return fieldDef && fieldDef.bin + ? `[${accessPathWithDatum(model.vgField(p.channel, {}), datum)}, ` + + `${accessPathWithDatum(model.vgField(p.channel, {binSuffix: 'end'}), datum)}]` + : `${accessPathWithDatum(p.field, datum)}`; + }) + .join(', '); // Only add a discrete selection to the store if a datum is present _and_ // the interaction isn't occurring on a group mark. This guards against @@ -32,7 +34,8 @@ export function signals(model: UnitModel, selCmpt: SelectionComponent) { on: [ { events: selCmpt.events, - update: `datum && item().mark.marktype !== 'group' ? ` + + update: + `datum && item().mark.marktype !== 'group' ? ` + `{unit: ${unitName(model)}, fields: ${fieldsSg}, values: [${values}]} : null`, force: true } diff --git a/src/compile/selection/transforms/project.ts b/src/compile/selection/transforms/project.ts index e05c1f72d6..741175139f 100644 --- a/src/compile/selection/transforms/project.ts +++ b/src/compile/selection/transforms/project.ts @@ -60,7 +60,7 @@ const project: TransformCompiler = { type = 'R-RE'; } - p.push(f[field] = {field, channel, type}); + p.push((f[field] = {field, channel, type})); } selCmpt.fields[channel] = field; @@ -77,9 +77,12 @@ const project: TransformCompiler = { signals: (model, selCmpt, signals) => { const name = selCmpt.name + TUPLE + TUPLE_FIELDS; const hasSignal = signals.filter(s => s.name === name); - return hasSignal.length ? signals : signals.concat({ - name, update: `${JSON.stringify(selCmpt.project)}` - }); + return hasSignal.length + ? signals + : signals.concat({ + name, + update: `${JSON.stringify(selCmpt.project)}` + }); } }; diff --git a/test/compile/selection/interval.test.ts b/test/compile/selection/interval.test.ts index 939553e48f..9c523d5455 100644 --- a/test/compile/selection/interval.test.ts +++ b/test/compile/selection/interval.test.ts @@ -179,8 +179,7 @@ describe('Interval Selections', () => { on: [ { events: [{signal: 'one_Horsepower'}], - update: - 'one_Horsepower ? {unit: "", fields: one_tuple_fields, values: [one_Horsepower]} : null' + update: 'one_Horsepower ? {unit: "", fields: one_tuple_fields, values: [one_Horsepower]} : null' } ] } diff --git a/test/compile/selection/parse.test.ts b/test/compile/selection/parse.test.ts index 47c5d2fa89..cf8663f91e 100644 --- a/test/compile/selection/parse.test.ts +++ b/test/compile/selection/parse.test.ts @@ -84,7 +84,9 @@ describe('Selection', () => { assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color', type: 'E'}]); + assert.sameDeepMembers(component['two'].project, [ + {field: 'Origin', channel: 'color', type: 'E'} + ]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); @@ -127,7 +129,9 @@ describe('Selection', () => { assert.equal(component.two.name, 'two'); assert.equal(component.two.type, 'multi'); assert.equal(component.two.toggle, 'event.ctrlKey'); - assert.sameDeepMembers(component['two'].project, [{field: 'Origin', channel: 'color', type: 'E'}]); + assert.sameDeepMembers(component['two'].project, [ + {field: 'Origin', channel: 'color', type: 'E'} + ]); assert.sameDeepMembers(component['two'].events, parseSelector('mouseover', 'scope')); assert.equal(component.three.name, 'three'); diff --git a/test/compile/selection/predicate.test.ts b/test/compile/selection/predicate.test.ts index c35cff9928..9abc4b5f6b 100644 --- a/test/compile/selection/predicate.test.ts +++ b/test/compile/selection/predicate.test.ts @@ -48,7 +48,10 @@ describe('Selection Predicate', () => { assert.equal(predicate(model, 'four'), '(vlSelectionTest("four_store", datum))'); - assert.equal(predicate(model, {not: 'one'}), '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", datum)))'); + assert.equal( + predicate(model, {not: 'one'}), + '!(length(data("one_store"))) || (!(vlSelectionTest("one_store", datum)))' + ); assert.equal( predicate(model, {not: {and: ['one', 'two']}}), @@ -59,7 +62,9 @@ describe('Selection Predicate', () => { assert.equal( predicate(model, {not: {and: ['one', 'four']}}), - '!(length(data("one_store"))) || ' + '(!((vlSelectionTest("one_store", datum)) && ' + '(vlSelectionTest("four_store", datum))))' + '!(length(data("one_store"))) || ' + + '(!((vlSelectionTest("one_store", datum)) && ' + + '(vlSelectionTest("four_store", datum))))' ); assert.equal( diff --git a/test/compile/selection/single.test.ts b/test/compile/selection/single.test.ts index 315eae7e9d..42c643a058 100644 --- a/test/compile/selection/single.test.ts +++ b/test/compile/selection/single.test.ts @@ -24,7 +24,7 @@ describe('Single Selection', () => { nearest: true, on: 'mouseover', encodings: ['y', 'color'], - resolve: "intersect" + resolve: 'intersect' } }));