vega-lite
Advanced tools
Comparing version 0.7.12 to 0.7.13
{ | ||
"name": "vega-lite", | ||
"main": "vega-lite.js", | ||
"version": "0.7.12", | ||
"version": "0.7.13", | ||
"homepage": "https://github.com/uwdata/vega-lite", | ||
@@ -6,0 +6,0 @@ "authors": [ |
@@ -8,3 +8,3 @@ 'use strict'; | ||
// runs the tests | ||
gulp.task('test', function() { | ||
gulp.task('coverage', function() { | ||
return gulp.src(['test/**/*.spec.js'], { read: false }) | ||
@@ -18,3 +18,3 @@ .pipe(mocha({ | ||
// quick test | ||
gulp.task('t', function() { | ||
gulp.task('test', function() { | ||
return gulp.src(['test/**/*.spec.js'], { read: false }) | ||
@@ -21,0 +21,0 @@ .pipe(mocha({ |
{ | ||
"name": "vega-lite", | ||
"author": "Jeffrey Heer, Dominik Moritz, Kanit \"Ham\" Wongsuphasawat", | ||
"version": "0.7.12", | ||
"version": "0.7.13", | ||
"collaborators": [ | ||
@@ -18,3 +18,3 @@ "Kanit Wongsuphasawat <kanitw@gmail.com> (http://kanitw.yellowpigz.com)", | ||
"lint": "gulp jshint", | ||
"test": "gulp t" | ||
"test": "gulp test" | ||
}, | ||
@@ -21,0 +21,0 @@ "repository": { |
@@ -14,7 +14,7 @@ # Vega-lite | ||
Use Vega-lite in the [online editor](https://uwdata.github.io/vega-lite/). | ||
If you are using Vega-lite for your project(s), please let us know by emailing us at [Vega-lite \[at\] cs.washington.edu](mailto:vega-lite@cs.washington.edu). Feedbacks are also welcomed. | ||
If you find a bug or have a feature request, please [create an issue](https://github.com/uwdata/vega-lite/issues/new). | ||
Use Vega-lite in the [online editor](https://uwdata.github.io/vega-lite/). | ||
The complete schema for specifications as [JSON schema](http://json-schema.org/) is at [spec.json](https://uwdata.github.io/vega-lite/spec.json). | ||
@@ -21,0 +21,0 @@ |
@@ -28,6 +28,8 @@ 'use strict'; | ||
def = axis.labels.format(def, name, encoding, stats); | ||
def = axis.labels.angle(def, encoding, name); | ||
// for x-axis, set ticks for Q or rotate scale for ordinal scale | ||
if (name == X) { | ||
if (encoding.isDimension(X) || encoding.isType(X, T)) { | ||
if ((encoding.isDimension(X) || encoding.isType(X, T)) && | ||
!('angle' in getter(def, ['properties', 'labels']))) { | ||
// TODO(kanitw): Jul 19, 2015 - #506 add condition for rotation | ||
@@ -201,2 +203,10 @@ def = axis.labels.rotate(def); | ||
axis.labels.angle = function(def, encoding, name) { | ||
var angle = encoding.axis(name).labelAngle; | ||
if (typeof angle === 'undefined') return def; | ||
setter(def, ['properties', 'labels', 'angle', 'value'], angle); | ||
return def; | ||
}; | ||
axis.labels.rotate = function(def) { | ||
@@ -203,0 +213,0 @@ var align = def.orient ==='top' ? 'left' : 'right'; |
@@ -11,3 +11,2 @@ 'use strict'; | ||
axis = compiler.axis = require('./axis'), | ||
filter = compiler.filter = require('./filter'), | ||
legend = compiler.legend = require('./legend'), | ||
@@ -17,4 +16,3 @@ marks = compiler.marks = require('./marks'), | ||
compiler.aggregate = require('./aggregate'); | ||
compiler.bin = require('./bin'); | ||
compiler.data = require('./data'); | ||
compiler.facet = require('./facet'); | ||
@@ -27,3 +25,2 @@ compiler.group = require('./group'); | ||
compiler.subfacet = require('./subfacet'); | ||
compiler.template = require('./template'); | ||
compiler.time = require('./time'); | ||
@@ -39,6 +36,7 @@ | ||
compiler.compileEncoding = function (encoding, stats) { | ||
// no need to pass stats if you pass in the data | ||
if (!stats && encoding.hasValues()) { | ||
stats = summary(encoding.data('values')).reduce(function(s, p) { | ||
stats = summary(encoding.data().values).reduce(function(s, p) { | ||
s[p.field] = p; | ||
@@ -49,16 +47,24 @@ return s; | ||
var layout = compiler.layout(encoding, stats), | ||
spec = compiler.template(encoding, layout, stats); | ||
var layout = compiler.layout(encoding, stats); | ||
// .data related stuff | ||
var rawTable = spec.data[0], | ||
dataTable = spec.data[1]; | ||
var spec = { | ||
width: layout.width, | ||
height: layout.height, | ||
padding: 'auto', | ||
data: compiler.data(encoding), | ||
// global scales contains only time unit scales | ||
scales: compiler.time.scales(encoding) | ||
}; | ||
rawTable = filter.addFilters(rawTable, encoding); // modify rawTable | ||
spec = compiler.time(spec, encoding); // modify rawTable, add scales | ||
dataTable = compiler.bin(dataTable, encoding); // modify dataTable | ||
var aggResult = compiler.aggregate(dataTable, encoding); // modify dataTable | ||
var sorting = compiler.sort(spec.data, encoding, stats); // append new data | ||
// 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), | ||
@@ -77,7 +83,6 @@ group = spec.marks[0], | ||
var details = aggResult.details, | ||
hasDetails = details && details.length > 0, | ||
stack = hasDetails && compiler.stack(spec.data, encoding, mdef, aggResult.facets); // modify spec.data, mdef.{from,properties} | ||
var details = encoding.details(), | ||
stack = encoding.isAggregate() && details.length > 0 && compiler.stack(spec.data, encoding, mdef); // modify spec.data, mdef.{from,properties} | ||
if (hasDetails && (stack || lineType)) { | ||
if (details.length > 0 && (stack || lineType)) { | ||
//subfacet to group stack / line together in one group | ||
@@ -103,6 +108,6 @@ compiler.subfacet(group, mdef, details, stack, encoding); | ||
if (encoding.has(ROW) || encoding.has(COL)) { | ||
spec = compiler.facet(group, encoding, layout, style, sorting, spec, singleScaleNames, stack, stats); | ||
spec = compiler.facet(group, encoding, layout, spec, singleScaleNames, stack, stats); | ||
spec.legends = legend.defs(encoding, style); | ||
} else { | ||
group.scales = scale.defs(singleScaleNames, encoding, layout, stats, style, sorting, {stack: stack}); | ||
group.scales = scale.defs(singleScaleNames, encoding, layout, stats, {stack: stack}); | ||
@@ -116,6 +121,6 @@ group.axes = []; | ||
filter.filterLessThanZero(dataTable, encoding); | ||
return spec; | ||
}; | ||
@@ -13,3 +13,3 @@ 'use strict'; | ||
function faceting(group, encoding, layout, style, sorting, spec, singleScaleNames, stack, stats) { | ||
function faceting(group, encoding, layout, spec, singleScaleNames, stack, stats) { | ||
var enter = group.properties.enter; | ||
@@ -106,4 +106,2 @@ var facetKeys = [], cellAxes = [], from, axesGrp; | ||
stats, | ||
style, | ||
sorting, | ||
{stack: stack, facet: true} | ||
@@ -110,0 +108,0 @@ )); // row/col scales + cell scales |
@@ -44,3 +44,3 @@ 'use strict'; | ||
def.title = encoding.fieldTitle(name); | ||
def.title = legend.title(name, encoding); | ||
def = legend.style(name, encoding, def, style); | ||
@@ -105,2 +105,10 @@ | ||
return def; | ||
}; | ||
}; | ||
legend.title = function(name, encoding) { | ||
var leg = encoding.field(name).legend; | ||
if (leg.title) return leg.title; | ||
return encoding.fieldTitle(name); | ||
}; |
@@ -10,3 +10,4 @@ 'use strict'; | ||
var defs = [], | ||
mark = marks[encoding.marktype()]; | ||
mark = marks[encoding.marktype()], | ||
from = encoding.dataTable(); | ||
@@ -24,3 +25,3 @@ // to add a background to text, we need to add it before the text | ||
type: 'rect', | ||
from: {data: TABLE}, | ||
from: {data: from}, | ||
properties: {enter: bg, update: bg} | ||
@@ -34,3 +35,3 @@ }); | ||
type: mark.type, | ||
from: {data: TABLE}, | ||
from: {data: from}, | ||
properties: {enter: p, update: p} | ||
@@ -37,0 +38,0 @@ }); |
@@ -7,3 +7,4 @@ 'use strict'; | ||
interpolate = require('d3-color').interpolateHsl, | ||
schema = require('../schema/schema'); | ||
schema = require('../schema/schema'), | ||
vlsort = require('./sort'); | ||
@@ -19,3 +20,3 @@ var scale = module.exports = {}; | ||
scale.defs = function(names, encoding, layout, stats, style, sorting, opt) { | ||
scale.defs = function(names, encoding, layout, stats, opt) { | ||
opt = opt || {}; | ||
@@ -27,3 +28,3 @@ | ||
type: scale.type(name, encoding), | ||
domain: scale.domain(name, encoding, stats, sorting, opt) | ||
domain: scale.domain(name, encoding, stats, opt) | ||
}; | ||
@@ -62,3 +63,3 @@ | ||
scale.domain = function (name, encoding, stats, sorting, opt) { | ||
scale.domain = function (name, encoding, stats, opt) { | ||
var field = encoding.field(name); | ||
@@ -97,2 +98,4 @@ | ||
// FIXME revise this part | ||
if ( useRawDomain && notCountOrSum && ( | ||
@@ -108,3 +111,7 @@ // Q always uses non-ordinal scale except when it's binned and thus uses ordinal scale. | ||
return {data: sorting.getDataset(name), field: encoding.fieldRef(name)}; | ||
var data = encoding.sort(name, stats).length > 0 ? | ||
vlsort.getDataName(name): | ||
encoding.dataTable(); | ||
return {data: data, field: encoding.fieldRef(name)}; | ||
}; | ||
@@ -111,0 +118,0 @@ |
@@ -7,10 +7,9 @@ 'use strict'; | ||
module.exports = addSortTransforms; | ||
module.exports = sort; | ||
// adds new transforms that produce sorted fields | ||
function addSortTransforms(data, encoding, stats, opt) { | ||
function sort(data, encoding, stats, opt) { | ||
// jshint unused:false | ||
var datasetMapping = {}; | ||
var counter = 0; | ||
@@ -32,3 +31,3 @@ encoding.forEach(function(field, encType) { | ||
var dataName = 'sorted' + counter++; | ||
var dataName = sort.getDataName(encType); | ||
@@ -57,12 +56,8 @@ var transforms = [ | ||
return { | ||
getDataset: function(encType) { | ||
var data = datasetMapping[encType]; | ||
if (!data) { | ||
return TABLE; | ||
} | ||
return data; | ||
} | ||
}; | ||
return data; | ||
} | ||
sort.getDataName = function(encType) { | ||
return 'sorted-' + encType; | ||
}; | ||
@@ -9,3 +9,3 @@ 'use strict'; | ||
function stacking(data, encoding, mdef, facets) { | ||
function stacking(data, encoding, mdef) { | ||
if (!marks[encoding.marktype()].stack) return false; | ||
@@ -18,3 +18,4 @@ | ||
isXMeasure = encoding.isMeasure(X), | ||
isYMeasure = encoding.isMeasure(Y); | ||
isYMeasure = encoding.isMeasure(Y), | ||
facets = encoding.facets(); | ||
@@ -36,3 +37,3 @@ if (isXMeasure && !isYMeasure) { | ||
name: STACKED, | ||
source: TABLE, | ||
source: encoding.dataTable(), | ||
transform: [{ | ||
@@ -39,0 +40,0 @@ type: 'aggregate', |
@@ -6,39 +6,6 @@ 'use strict'; | ||
module.exports = time; | ||
var time = module.exports = {}; | ||
var LONG_DATE = new Date(2014, 8, 17); | ||
function time(spec, encoding) { // FIXME refactor to reduce side effect #276 | ||
// jshint unused:false | ||
var timeFields = {}, timeUnits = {}; | ||
// find unique formula transformation and bin function | ||
encoding.forEach(function(field, encType) { | ||
if (field.type === T && field.timeUnit) { | ||
timeFields[encoding.fieldRef(encType)] = { | ||
field: field, | ||
encType: encType | ||
}; | ||
timeUnits[field.timeUnit] = true; | ||
} | ||
}); | ||
// add formula transform | ||
var data = spec.data[0], | ||
transform = data.transform = data.transform || []; | ||
for (var f in timeFields) { | ||
var tf = timeFields[f]; | ||
time.transform(transform, encoding, tf.encType, tf.field); | ||
} | ||
// add scales | ||
var scales = spec.scales = spec.scales || []; | ||
for (var timeUnit in timeUnits) { | ||
var scale = time.scale.def(timeUnit, encoding); | ||
if (scale) scales.push(scale); | ||
} | ||
return spec; | ||
} | ||
time.cardinality = function(field, stats, filterNull, type) { | ||
@@ -66,2 +33,8 @@ var timeUnit = field.timeUnit; | ||
time.formula = function(timeUnit, fieldRef) { | ||
// TODO(kanitw): add formula to other time format | ||
var fn = 'utc' + timeUnit; | ||
return fn + '(' + fieldRef + ')'; | ||
}; | ||
time.maxLength = function(timeUnit, encoding) { | ||
@@ -90,22 +63,2 @@ switch (timeUnit) { | ||
function fieldFn(func, field) { | ||
return 'utc' + func + '(d.data.'+ field.name +')'; | ||
} | ||
/** | ||
* @return {String} date binning formula of the given field | ||
*/ | ||
time.formula = function(field) { | ||
return fieldFn(field.timeUnit, field); | ||
}; | ||
/** add formula transforms to data */ | ||
time.transform = function(transform, encoding, encType, field) { | ||
transform.push({ | ||
type: 'formula', | ||
field: encoding.fieldRef(encType), | ||
expr: time.formula(field) | ||
}); | ||
}; | ||
time.range = function(timeUnit, encoding) { | ||
@@ -131,2 +84,20 @@ var labelLength = encoding.config('timeScaleLabelLength'), | ||
/** | ||
* @param {Object} encoding | ||
* @return {Array} scales for time unit names | ||
*/ | ||
time.scales = function(encoding) { | ||
var scales = encoding.reduce(function(scales, field) { | ||
var timeUnit = field.timeUnit; | ||
if (field.type === T && timeUnit && !scales[timeUnit]) { | ||
var scale = time.scale.def(field.timeUnit, encoding); | ||
if (scale) scales[timeUnit] = scale; | ||
} | ||
return scales; | ||
}, {}); | ||
return util.vals(scales); | ||
}; | ||
time.scale = {}; | ||
@@ -133,0 +104,0 @@ |
@@ -246,2 +246,3 @@ 'use strict'; | ||
proto.isTypes = function(et, type) { | ||
@@ -280,2 +281,6 @@ var field = this.field(et); | ||
proto.dataTable = function() { | ||
return this.isAggregate() ? AGGREGATE : RAW; | ||
}; | ||
Encoding.isAggregate = function(spec) { | ||
@@ -301,2 +306,22 @@ return vlenc.isAggregate(spec.encoding); | ||
proto.details = function() { | ||
var encoding = this; | ||
return this.reduce(function(refs, field, encType) { | ||
if (!field.aggregate && (encType !== X && encType !== Y)) { | ||
refs.push(encoding.fieldRef(encType)); | ||
} | ||
return refs; | ||
}, []); | ||
}; | ||
proto.facets = function() { | ||
var encoding = this; | ||
return this.reduce(function(refs, field, encType) { | ||
if (!field.aggregate && (encType == ROW || encType == COL)) { | ||
refs.push(encoding.fieldRef(encType)); | ||
} | ||
return refs; | ||
}, []); | ||
}; | ||
proto.cardinality = function(encType, stats) { | ||
@@ -310,4 +335,4 @@ return vlfield.cardinality(this.field(encType), stats, this.config('filterNull')); | ||
proto.data = function(name) { | ||
return name ? this._data[name] : this._data; | ||
proto.data = function() { | ||
return this._data; | ||
}; | ||
@@ -317,3 +342,3 @@ | ||
proto.hasValues = function() { | ||
var vals = this.data('values'); | ||
var vals = this.data().values; | ||
return vals && vals.length; | ||
@@ -320,0 +345,0 @@ }; |
@@ -20,2 +20,3 @@ 'use strict'; | ||
* opt.data - include 'data.' | ||
* opt.d - include 'd.' | ||
* opt.fn - replace fn with custom function prefix | ||
@@ -29,3 +30,5 @@ * opt.prefn - prepend fn with custom function prefix | ||
var f = (opt.data ? 'data.' : '') + (opt.prefn || ''), | ||
var f = (opt.d ? 'd.' : '') + | ||
(opt.data ? 'data.' : '') + | ||
(opt.prefn || ''), | ||
nofn = opt.nofn || opt.fn, | ||
@@ -32,0 +35,0 @@ name = field.name; |
@@ -6,3 +6,3 @@ 'use strict'; | ||
g.TABLE = 'table'; | ||
g.AGGREGATE = 'aggregate'; | ||
g.RAW = 'raw'; | ||
@@ -9,0 +9,0 @@ g.STACKED = 'stacked'; |
@@ -168,3 +168,3 @@ // Package of defining Vega-lite Specification's json schema | ||
}, | ||
ticks :{ | ||
ticks: { | ||
type: 'integer', | ||
@@ -202,3 +202,8 @@ default: 5, | ||
description: 'Truncate labels that are too long.' | ||
} | ||
}, | ||
labelAngle: { | ||
type: 'integer', | ||
default: undefined, // auto | ||
description: 'Angle by which to rotate labels. Set to 0 to force horizontal.' | ||
}, | ||
} | ||
@@ -262,4 +267,10 @@ } | ||
legend: { | ||
type: 'boolean', | ||
default: true | ||
type: 'object', | ||
properties: { | ||
title: { | ||
type: 'string', | ||
default: undefined, | ||
description: 'A title for the legend. (Shows field name and its function by default.)' | ||
} | ||
} | ||
} | ||
@@ -266,0 +277,0 @@ } |
@@ -7,2 +7,3 @@ 'use strict'; | ||
util.extend(util, require('datalib/src/stats')); | ||
util.extend(util, require('./logger')('[VL Error]')); | ||
util.bin = require('datalib/src/bins/bins'); | ||
@@ -103,5 +104,1 @@ | ||
util.error = function(msg) { | ||
console.error('[VL Error]', msg); | ||
}; | ||
@@ -72,2 +72,13 @@ 'use strict'; | ||
describe('labels.angle()', function () { | ||
it('should set explicitly specified angle', function () { | ||
var def = axis.labels.angle({}, Encoding.fromSpec({ | ||
encoding: { | ||
x: {name: 'a', type: 'T', axis:{labelAngle: 90}} | ||
} | ||
}), 'x'); | ||
expect(def.properties.labels.angle).to.eql({value: 90}); | ||
}); | ||
}); | ||
describe('labels.rotate()', function () { | ||
@@ -74,0 +85,0 @@ // FIXME(kanitw): Jul 19, 2015 - write test |
@@ -30,7 +30,2 @@ 'use strict'; | ||
describe('domain()', function() { | ||
var sortingReturn = 'sorted', | ||
sorting = { | ||
getDataset: function() {return 'sorted';} | ||
}; | ||
it('should return correct stack', function() { | ||
@@ -43,3 +38,3 @@ var domain = vlscale.domain('y', Encoding.fromSpec({ | ||
} | ||
}), {}, {}, { | ||
}), {}, { | ||
stack: 'y', | ||
@@ -63,3 +58,3 @@ facet: true | ||
} | ||
}), {}, {}, { | ||
}), {}, { | ||
stack: 'y', | ||
@@ -86,3 +81,3 @@ facet: true | ||
} | ||
}), {origin: {min: -5, max:48}}, sorting, {}); | ||
}), {origin: {min: -5, max:48}}, {}); | ||
@@ -103,3 +98,3 @@ expect(domain).to.eql([-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); | ||
} | ||
}), {}, {}, {}); | ||
}), {}, {}); | ||
@@ -120,5 +115,5 @@ expect(domain.data).to.eql(RAW); | ||
} | ||
}), {}, sorting, {}); | ||
}), {}, {}); | ||
expect(domain.data).to.eql(sortingReturn); | ||
expect(domain.data).to.eql(AGGREGATE); | ||
}); | ||
@@ -136,3 +131,3 @@ | ||
} | ||
}), {}, {}, {}); | ||
}), {}, {}); | ||
@@ -153,3 +148,3 @@ expect(domain.data).to.eql(RAW); | ||
} | ||
}), {}, {}, {}); | ||
}), {}, {}); | ||
@@ -171,3 +166,3 @@ expect(domain.data).to.eql(RAW); | ||
} | ||
}), {}, sorting, {}); | ||
}), {}, {}); | ||
@@ -187,5 +182,5 @@ expect(domain).to.eql([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); | ||
} | ||
}), {}, sorting, {}); | ||
}), {}, {}); | ||
expect(domain.data).to.eql(sortingReturn); | ||
expect(domain.data).to.eql(AGGREGATE); | ||
}); | ||
@@ -192,0 +187,0 @@ |
@@ -22,5 +22,6 @@ 'use strict'; | ||
}), | ||
data = [{name: RAW}, {name: TABLE}], | ||
sorting = vlsort(data, encoding, {}); | ||
data = [{name: RAW}, {name: AGGREGATE}]; | ||
vlsort(data, encoding, {}); | ||
it('should add new data and transform', function() { | ||
@@ -56,8 +57,2 @@ expect(data.length).to.equal(4); | ||
}); | ||
it('should set correct mapping', function() { | ||
expect(sorting.getDataset('x')).to.equal('sorted0'); | ||
expect(sorting.getDataset('color')).to.equal('sorted1'); | ||
expect(sorting.getDataset('y')).to.equal('table'); | ||
}); | ||
}); |
@@ -34,3 +34,3 @@ 'use strict'; | ||
var tableData = vgSpec.data.filter(function(data) { | ||
return data.name === 'table'; | ||
return data.name === 'aggregate'; | ||
}); | ||
@@ -60,3 +60,3 @@ expect(tableData.length).to.equal(1); | ||
var tableData = vgSpec.data.filter(function(data) { | ||
return data.name === 'table'; | ||
return data.name === 'aggregate'; | ||
}); | ||
@@ -63,0 +63,0 @@ expect(tableData.length).to.equal(1); |
@@ -16,16 +16,7 @@ 'use strict'; | ||
}), | ||
spec = time({data: [{name: RAW}, {name: TABLE}]}, encoding, {}); | ||
scales = time.scales(encoding); | ||
it('should add formula transform', function() { | ||
var data = spec.data[0]; | ||
expect(data.transform).to.be.ok; | ||
expect(data.transform.filter(function(t) { | ||
return t.type === 'formula' && t.field === encoding.fieldRef('x') && | ||
t.expr === time.formula(encoding._enc.x); | ||
}).length).to.be.above(0); | ||
}); | ||
it('should add custom axis scale', function() { | ||
expect(spec.scales.filter(function(scale) { | ||
expect(scales.filter(function(scale) { | ||
return scale.name == 'time-'+ timeUnit; | ||
@@ -32,0 +23,0 @@ }).length).to.equal(1); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7522511
120162
91