Repository: vega/vega-lite
Pull request #593 (2015-10-03 14:38:01)

Replace the eliminated `group` mark properties with `field.group`
Replace the eliminated `group` mark properties with `field.group`

Please merge 590 first !  (See [Branch Specific Diff](https://github.com/uwdata/vega-lite/compare/kw/vg2-data...kw/vg2-group))




Patch:
diff --git a/editor/bower.json b/editor/bower.json
index 12708b49b..c85e79739 100644
--- a/editor/bower.json
+++ b/editor/bower.json
@@ -15,6 +15,6 @@
     "tests"
   ],
   "dependencies": {
-    "vega": "^1.5.4"
+    "vega": "^2.2.6"
   }
 }
diff --git a/gallery/bower.json b/gallery/bower.json
index fc0b3cc8b..835ae31ad 100644
--- a/gallery/bower.json
+++ b/gallery/bower.json
@@ -15,7 +15,7 @@
     "tests"
   ],
   "dependencies": {
-    "vega": "^1.0.0",
+    "vega": "^2.2.6",
     "angular": "^1.4.3"
   }
 }
diff --git a/src/Encoding.js b/src/Encoding.js
index 9fa5d2c8a..90d3e86ef 100644
--- a/src/Encoding.js
+++ b/src/Encoding.js
@@ -18,7 +18,7 @@ module.exports = (function() {
     this._enc = specExtended.encoding;
     this._config = specExtended.config;
     this._filter = specExtended.filter;
-    // this._vega2 = true;
+    this._vega2 = true;
   }
 
   var proto = Encoding.prototype;
diff --git a/src/compiler/axis.js b/src/compiler/axis.js
index 759fae986..d3e49d7f9 100644
--- a/src/compiler/axis.js
+++ b/src/compiler/axis.js
@@ -101,9 +101,9 @@ axis.grid = function(def, name, encoding, layout) {
           value: def.offset
         },
         x2: {
+          field: {group: 'mark.group.width'},
           offset: def.offset + (layout.cellWidth * 0.05),
           // default value(s) -- vega doesn't do recursive merge
-          group: 'mark.group.width',
           mult: 1
         },
         stroke: { value: encoding.config('cellGridColor') },
@@ -192,8 +192,9 @@ axis.labels.format = function (def, name, encoding, stats) {
   } else if (encoding.isTypes(name, [N, O]) && encoding.axis(name).maxLabelLength) {
     setter(def,
       ['properties','labels','text','template'],
-      '{{data | truncate:' + encoding.axis(name).maxLabelLength + '}}'
-      );
+      '{{' + (encoding._vega2 ?  'datum.data': 'data') +
+      ' | truncate:' + encoding.axis(name).maxLabelLength + '}}'
+    );
   }
 
   return def;
diff --git a/src/compiler/compiler.js b/src/compiler/compiler.js
index 3129adfbd..a826e311c 100644
--- a/src/compiler/compiler.js
+++ b/src/compiler/compiler.js
@@ -17,7 +17,6 @@ var Encoding = require('../Encoding'),
 
 compiler.data = require('./data');
 compiler.facet = require('./facet');
-compiler.group = require('./group');
 compiler.layout = require('./layout');
 compiler.sort = require('./sort');
 compiler.stack = require('./stack');
@@ -57,29 +56,33 @@ compiler.compileEncoding = function (encoding, stats) {
       padding: 'auto',
       data: compiler.data(encoding),
       // global scales contains only time unit scales
-      scales: compiler.time.scales(encoding)
+      scales: compiler.time.scales(encoding),
+      marks: [{
+        _name: 'cell',
+        type: 'group',
+        properties: {
+          enter: {
+            width: layout.cellWidth ?
+                     {value: layout.cellWidth} :
+                     {field: {group: 'width'}},
+            height: layout.cellHeight ?
+                    {value: layout.cellHeight} :
+                    {field: {group: 'height'}}
+          }
+        }
+      }]
     };
 
+  var group = spec.marks[0];
+
   // FIXME remove compiler.sort after migrating to vega 2.
   spec.data = compiler.sort(spec.data, encoding, stats); // append new data
 
   // marks
-
-  // TODO this line is temporary and should be refactored
-  spec.marks = [compiler.group.def('cell', {
-    width: layout.cellWidth ? {value: layout.cellWidth} : undefined,
-    height: layout.cellHeight ? {value: layout.cellHeight} : undefined
-  })];
-
   var style = compiler.style(encoding, stats),
-    group = spec.marks[0],
-    mdefs = marks.def(encoding, layout, style, stats),
+    mdefs = group.marks = marks.def(encoding, layout, style, stats),
     mdef = mdefs[mdefs.length - 1];  // TODO: remove this dirty hack by refactoring the whole flow
 
-  for (var i = 0; i < mdefs.length; i++) {
-    group.marks.push(mdefs[i]);
-  }
-
   var lineType = marks[encoding.marktype()].line;
 
   // handle subfacets
diff --git a/src/compiler/data.js b/src/compiler/data.js
index dab1f0541..0dfe6d8c5 100644
--- a/src/compiler/data.js
+++ b/src/compiler/data.js
@@ -94,12 +94,12 @@ var BINARY = {
 data.raw.transform.time = function(encoding) {
   return encoding.reduce(function(transform, field, encType) {
     if (field.type === T && field.timeUnit) {
+      var fieldRef = encoding.fieldRef(encType, {nofn: true, d: !encoding._vega2, datum: encoding._vega2});
+
       transform.push({
         type: 'formula',
         field: encoding.fieldRef(encType),
-        expr: time.formula(field.timeUnit,
-                           encoding.fieldRef(encType, {nofn: true, d: true})
-                          )
+        expr: time.formula(field.timeUnit, fieldRef)
       });
     }
     return transform;
@@ -126,7 +126,7 @@ data.raw.transform.filter = function(encoding) {
     var operator = filter.operator;
     var operands = filter.operands;
 
-    var d = 'd.' + (encoding._vega2 ? '' : 'data.');
+    var d = encoding._vega2 ? 'datum.' : 'd.data.';
 
     if (BINARY[operator]) {
       // expects a field and a value
@@ -201,7 +201,7 @@ data.filterNonPositive = function(dataTable, encoding) {
     if (encoding.scale(encType).type === 'log') {
       dataTable.transform.push({
         type: 'filter',
-        test: encoding.fieldRef(encType, {d: 1}) + ' > 0'
+        test: encoding.fieldRef(encType, encoding._vega2 ? {datum: 1} : {d: 1}) + ' > 0'
       });
     }
   });
diff --git a/src/compiler/facet.js b/src/compiler/facet.js
index e006b2a17..a728605d7 100644
--- a/src/compiler/facet.js
+++ b/src/compiler/facet.js
@@ -5,11 +5,30 @@ require('../globals');
 var util = require('../util');
 
 var axis = require('./axis'),
-  groupdef = require('./group').def,
   scale = require('./scale');
 
 module.exports = faceting;
 
+function groupdef(name, opt) {
+  opt = opt || {};
+  return {
+    _name: name || undefined,
+    type: 'group',
+    from: opt.from,
+    properties: {
+      enter: {
+        x: opt.x || undefined,
+        y: opt.y || undefined,
+        width: opt.width || {field: {group: 'width'}},
+        height: opt.height || {field: {group: 'height'}}
+      }
+    },
+    scales: opt.scales || undefined,
+    axes: opt.axes || undefined,
+    marks: opt.marks || []
+  };
+}
+
 function faceting(group, encoding, layout, spec, singleScaleNames, stack, stats) {
   var enter = group.properties.enter;
   var facetKeys = [], cellAxes = [], from, axesGrp;
diff --git a/src/compiler/group.js b/src/compiler/group.js
deleted file mode 100644
index d691cc651..000000000
--- a/src/compiler/group.js
+++ /dev/null
@@ -1,25 +0,0 @@
-'use strict';
-
-module.exports = {
-  def: groupdef
-};
-
-function groupdef(name, opt) {
-  opt = opt || {};
-  return {
-    _name: name || undefined,
-    type: 'group',
-    from: opt.from,
-    properties: {
-      enter: {
-        x: opt.x || undefined,
-        y: opt.y || undefined,
-        width: opt.width || {group: 'width'},
-        height: opt.height || {group: 'height'}
-      }
-    },
-    scales: opt.scales || undefined,
-    axes: opt.axes || undefined,
-    marks: opt.marks || []
-  };
-}
diff --git a/src/compiler/marks.js b/src/compiler/marks.js
index 355433b25..f6b97c1eb 100644
--- a/src/compiler/marks.js
+++ b/src/compiler/marks.js
@@ -130,12 +130,15 @@ function bar_props(e, layout, style) {
   // y's & height
   if (e.isMeasure(Y)) {
     p.y = {scale: Y, field: e.fieldRef(Y)};
-    p.y2 = {group: 'height'};
+    p.y2 = {field: {group: 'height'}};
   } else {
     if (e.has(Y)) { // is ordinal
       p.yc = {scale: Y, field: e.fieldRef(Y)};
     } else {
-      p.y2 = {group: 'height', offset: -e.config('singleBarOffset')};
+      p.y2 = {
+        field: {group: 'height'},
+        offset: -e.config('singleBarOffset')
+      };
     }
 
     if (e.has(SIZE)) {
@@ -231,7 +234,7 @@ function line_props(e,layout, style) {
   if (e.has(Y)) {
     p.y = {scale: Y, field: e.fieldRef(Y)};
   } else if (!e.has(Y)) {
-    p.y = {group: 'height'};
+    p.y = {field: {group: 'height'}};
   }
 
   // stroke
@@ -273,7 +276,7 @@ function area_props(e, layout, style) {
   } else if (e.has(Y)) {
     p.y = {scale: Y, field: e.fieldRef(Y)};
   } else {
-    p.y = {group: 'height'};
+    p.y = {field: {group: 'height'}};
   }
 
   // fill
diff --git a/src/compiler/subfacet.js b/src/compiler/subfacet.js
index 6a45ca8e4..430b85959 100644
--- a/src/compiler/subfacet.js
+++ b/src/compiler/subfacet.js
@@ -2,17 +2,25 @@
 
 require('../globals');
 
-var groupdef = require('./group').def;
-
 module.exports = subfaceting;
 
 function subfaceting(group, mdef, details, stack, encoding) {
-  var m = group.marks,
-    g = groupdef('subfacet', {marks: m});
+  var m = group.marks;
+  var g = {
+    _name: 'subfacet',
+    type: 'group',
+    from: mdef.from,
+    properties: {
+      enter: {
+        width: {field: {group: 'width'}},
+        height: {field: {group: 'height'}}
+      }
+    },
+    marks: m
+  };
 
   group.marks = [g];
-  g.from = mdef.from;
-  delete mdef.from;
+  delete mdef.from; // (move to the new g)
 
   //TODO test LOD -- we should support stack / line without color (LOD) field
   var trans = (g.from.transform || (g.from.transform = []));
diff --git a/src/field.js b/src/field.js
index c8702986b..59a39ba6e 100644
--- a/src/field.js
+++ b/src/field.js
@@ -17,6 +17,7 @@ var vlfield = module.exports = {};
  * @param opt
  *   opt.nofn -- exclude bin, aggregate, timeUnit
  *   opt.data - include 'data.'
+ *   opt.datum - include 'datum.'
  *   opt.d - include 'd.'
  *   opt.fn - replace fn with custom function prefix
  *   opt.prefn - prepend fn with custom function prefix
@@ -26,7 +27,8 @@ var vlfield = module.exports = {};
 vlfield.fieldRef = function(field, opt) {
   opt = opt || {};
 
-  var f = (opt.d ? 'd.' : '') +
+  var f = (opt.datum ? 'datum.' : '') +
+          (opt.d ? 'd.' : '') +
           (opt.data ? 'data.' : '') +
           (opt.prefn || ''),
     nofn = opt.nofn || opt.fn,


Test patch:
diff --git a/test/compiler/data.spec.js b/test/compiler/data.spec.js
index ea7863174..8465ab0b8 100644
--- a/test/compiler/data.spec.js
+++ b/test/compiler/data.spec.js
@@ -36,7 +36,7 @@ describe('data', function () {
       var rawTransform = _data[0].transform;
       expect(rawTransform[rawTransform.length - 1]).to.eql({
         type: 'filter',
-        test: 'd.data.b > 0'
+        test: 'datum.b > 0'
       });
     });
   });
@@ -122,8 +122,8 @@ describe('data.raw', function() {
         var transform = data.raw.transform.bin(encoding);
         expect(transform[0]).to.eql({
           type: 'bin',
-          field: 'data.Acceleration',
-          output: 'data.bin_Acceleration',
+          field: 'Acceleration',
+          output: 'bin_Acceleration',
           maxbins: 15
         });
       });
@@ -135,8 +135,8 @@ describe('data.raw', function() {
 
         expect(transform[0]).to.eql({
           type: 'filter',
-          test: '(d.data.a!==null) && (d.data.Acceleration!==null)' +
-          ' && (d.data.a > b) && (d.data.c == d)'
+          test: '(datum.a!==null) && (datum.Acceleration!==null)' +
+          ' && (datum.a > b) && (datum.c == d)'
         });
       });
 
@@ -159,8 +159,8 @@ describe('data.raw', function() {
         var transform = data.raw.transform.time(encoding);
         expect(transform[0]).to.eql({
           type: 'formula',
-          field: 'data.year_a',
-          expr: 'utcyear(d.data.a)'
+          field: 'year_a',
+          expr: 'utcyear(datum.a)'
         });
       });
     });
@@ -199,10 +199,10 @@ describe('data.aggregated', function () {
       "source": "raw",
       "transform": [{
         "type": "aggregate",
-        "groupby": ["data.origin"],
+        "groupby": ["origin"],
         "fields": [{
           "op": "sum",
-          "field": "data.Acceleration"
+          "field": "Acceleration"
         },{
           "op": "count",
           "field": "*"
diff --git a/test/compiler/marks.spec.js b/test/compiler/marks.spec.js
index bb13f77c2..36b8e840f 100644
--- a/test/compiler/marks.spec.js
+++ b/test/compiler/marks.spec.js
@@ -18,7 +18,7 @@ describe('compile.marks', function() {
           e = Encoding.fromSpec(f),
           def = marks.bar.prop(e, mockLayout, {});
       it('should end on axis', function() {
-        expect(def.y2).to.eql({group: 'height'});
+        expect(def.y2).to.eql({field: {group: 'height'}});
       });
       it('should has no height', function(){
         expect(def.height).to.be.undefined;
@@ -42,7 +42,7 @@ describe('compile.marks', function() {
           e = Encoding.fromSpec(f),
           def = marks.bar.prop(e, mockLayout, {});
       it('should end on axis', function() {
-        expect(def.y2).to.eql({group: 'height'});
+        expect(def.y2).to.eql({field: {group: 'height'}});
       });
       it('should have no height', function(){
         expect(def.height).to.be.undefined;
@@ -64,7 +64,7 @@ describe('compile.marks', function() {
       });
       it('should have y-offset', function(){
         expect(def.y2).to.eql({
-          group: 'height',
+          field: {group: 'height'},
           offset: -5 // -config.singleBarOffset
         });
       });
@@ -80,7 +80,7 @@ describe('compile.marks', function() {
         expect(def.y).to.eql({value: e.bandSize(Y, mockLayout.y.useSmallBand) / 2});
       });
       it('should scale on x', function() {
-        expect(def.x).to.eql({scale: X, field: "data.year"});
+        expect(def.x).to.eql({scale: X, field: "year"});
       });
     });
 
@@ -92,7 +92,7 @@ describe('compile.marks', function() {
         expect(def.x).to.eql({value: e.bandSize(X, mockLayout.x.useSmallBand) / 2});
       });
       it('should scale on y', function() {
-        expect(def.y).to.eql({scale: Y, field: "data.year"});
+        expect(def.y).to.eql({scale: Y, field: "year"});
       });
     });
 
@@ -101,10 +101,10 @@ describe('compile.marks', function() {
           e = Encoding.fromSpec(f),
           def = marks.point.prop(e, mockLayout, {});
       it('should scale on x', function() {
-        expect(def.x).to.eql({scale: X, field: "data.year"});
+        expect(def.x).to.eql({scale: X, field: "year"});
       });
       it('should scale on y', function(){
-        expect(def.y).to.eql({scale: Y, field: "data.yield"});
+        expect(def.y).to.eql({scale: Y, field: "yield"});
       });
     });
 
@@ -114,7 +114,7 @@ describe('compile.marks', function() {
             e = Encoding.fromSpec(f),
             def = marks.point.prop(e, mockLayout, {});
         it('should have scale for size', function () {
-          expect(def.size).to.eql({scale: SIZE, field: "data.count"});
+          expect(def.size).to.eql({scale: SIZE, field: "count"});
         });
       });
 
@@ -123,7 +123,7 @@ describe('compile.marks', function() {
             e = Encoding.fromSpec(f),
             def = marks.point.prop(e, mockLayout, {});
         it('should have scale for color', function () {
-          expect(def.stroke).to.eql({scale: COLOR, field: "data.yield"});
+          expect(def.stroke).to.eql({scale: COLOR, field: "yield"});
         });
       });
 
@@ -132,7 +132,7 @@ describe('compile.marks', function() {
             e = Encoding.fromSpec(f),
             def = marks.point.prop(e, mockLayout, {});
         it('should have scale for shape', function () {
-          expect(def.shape).to.eql({scale: SHAPE, field: "data.bin_yield"});
+          expect(def.shape).to.eql({scale: SHAPE, field: "bin_yield"});
         });
       });
     });
@@ -144,10 +144,10 @@ describe('compile.marks', function() {
           e = Encoding.fromSpec(f),
           def = marks.line.prop(e, mockLayout, {});
       it('should have scale for x', function() {
-        expect(def.x).to.eql({scale: X, field: "data.year"});
+        expect(def.x).to.eql({scale: X, field: "year"});
       });
       it('should have scale for y', function(){
-        expect(def.y).to.eql({scale: Y, field: "data.yield"});
+        expect(def.y).to.eql({scale: Y, field: "yield"});
       });
     });
 
@@ -157,7 +157,7 @@ describe('compile.marks', function() {
             e = Encoding.fromSpec(f),
             def = marks.line.prop(e, mockLayout, {});
         it('should have scale for color', function () {
-          expect(def.stroke).to.eql({scale: COLOR, field: "data.Acceleration"});
+          expect(def.stroke).to.eql({scale: COLOR, field: "Acceleration"});
         });
       });
     });
@@ -169,10 +169,10 @@ describe('compile.marks', function() {
           e = Encoding.fromSpec(f),
           def = marks.area.prop(e, mockLayout, {});
       it('should have scale for x', function() {
-        expect(def.x).to.eql({scale: X, field: "data.Displacement"});
+        expect(def.x).to.eql({scale: X, field: "Displacement"});
       });
       it('should have scale for y', function(){
-        expect(def.y).to.eql({scale: Y, field: "data.Acceleration"});
+        expect(def.y).to.eql({scale: Y, field: "Acceleration"});
       });
     });
 
@@ -182,7 +182,7 @@ describe('compile.marks', function() {
             e = Encoding.fromSpec(f),
             def = marks.area.prop(e, mockLayout, {});
         it('should have scale for color', function () {
-          expect(def.fill).to.eql({scale: COLOR, field: "data.Miles_per_Gallon"});
+          expect(def.fill).to.eql({scale: COLOR, field: "Miles_per_Gallon"});
         });
       });
     });
diff --git a/test/compiler/scale.spec.js b/test/compiler/scale.spec.js
index 7985be249..57a40838b 100644
--- a/test/compiler/scale.spec.js
+++ b/test/compiler/scale.spec.js
@@ -41,7 +41,7 @@ describe('vl.compile.scale', function() {
 
       expect(domain).to.eql({
         data: 'stacked',
-        field: 'data.max_sum_origin'
+        field: 'max_sum_origin'
       });
     });
 
@@ -60,7 +60,7 @@ describe('vl.compile.scale', function() {
 
       expect(domain).to.eql({
         data: 'stacked',
-        field: 'data.max_sum_sum_origin'
+        field: 'max_sum_sum_origin'
       });
     });
 
diff --git a/test/compiler/sort.spec.js b/test/compiler/sort.spec.js
index 1e1338068..14740c20b 100644
--- a/test/compiler/sort.spec.js
+++ b/test/compiler/sort.spec.js
@@ -29,28 +29,28 @@ describe('Sort', function() {
     expect(data[2].transform).to.deep.equal([
       {
         type: 'aggregate',
-        groupby: [ 'data.foo' ],
+        groupby: [ 'foo' ],
         fields: [{
-          field: 'data.bar',
+          field: 'bar',
           op: 'avg'
         }]
       },
-      { type: 'sort', by: [ 'data.avg_bar' ] }
+      { type: 'sort', by: [ 'avg_bar' ] }
     ]);
 
     expect(data[3].transform).to.deep.equal([
       {
         type: 'aggregate',
-        groupby: [ 'data.baz' ],
+        groupby: [ 'baz' ],
         fields: [{
-          field: 'data.bar',
+          field: 'bar',
           op: 'sum'
         }, {
-          field: 'data.foo',
+          field: 'foo',
           op: 'max'
         }]
       },
-      { type: 'sort', by: [ 'data.sum_bar', '-data.max_foo' ] }
+      { type: 'sort', by: [ 'sum_bar', '-max_foo' ] }
     ]);
   });
 });
diff --git a/test/compiler/stack.spec.js b/test/compiler/stack.spec.js
index 5fbd749c1..ce85e19cb 100644
--- a/test/compiler/stack.spec.js
+++ b/test/compiler/stack.spec.js
@@ -39,14 +39,14 @@ describe('vl.compile.stack()', function () {
         return t.type === 'aggregate';
       })[0];
       expect(tableAggrTransform.groupby.length).to.equal(2);
-      expect(tableAggrTransform.groupby.indexOf('data.bin_Cost__Total_$')).to.gt(-1);
+      expect(tableAggrTransform.groupby.indexOf('bin_Cost__Total_$')).to.gt(-1);
 
       var stackedData = vgSpec.data.filter(function(data) {
         return data.name === 'stacked';
       });
       expect(stackedData.length).to.equal(1);
       var stackedAggrTransform = stackedData[0].transform[0];
-      expect(stackedAggrTransform.groupby[0]).to.equal('data.bin_Cost__Total_$');
+      expect(stackedAggrTransform.groupby[0]).to.equal('bin_Cost__Total_$');
     });
   });
 
@@ -64,7 +64,7 @@ describe('vl.compile.stack()', function () {
         return t.type === 'aggregate';
       })[0];
       expect(tableAggrTransform.groupby.length).to.equal(2);
-      expect(tableAggrTransform.groupby.indexOf('data.bin_Cost__Total_$')).to.gt(-1);
+      expect(tableAggrTransform.groupby.indexOf('bin_Cost__Total_$')).to.gt(-1);
 
       var stackedData = vgSpec.data.filter(function(data) {
         return data.name === 'stacked';
@@ -72,7 +72,7 @@ describe('vl.compile.stack()', function () {
 
       expect(stackedData.length).to.equal(1);
       var stackedAggrTransform = stackedData[0].transform[0];
-      expect(stackedAggrTransform.groupby[0]).to.equal('data.bin_Cost__Total_$');
+      expect(stackedAggrTransform.groupby[0]).to.equal('bin_Cost__Total_$');
     });
   });