diff --git a/.babelrc b/.babelrc
index 684fff6..9d8d516 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1 +1 @@
-{ "presets": ["env"] }
+{ "presets": ["es2015"] }
diff --git a/build/webcharts.js b/build/webcharts.js
index 01afe8c..baf8dad 100644
--- a/build/webcharts.js
+++ b/build/webcharts.js
@@ -6,73 +6,7 @@
: (global.webCharts = factory(global.d3));
})(this, function(d3) {
'use strict';
- var version = '1.11.0';
-
- function init(data) {
- var _this = this;
-
- var test = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- if (d3.select(this.div).select('.loader').empty()) {
- d3
- .select(this.div)
- .insert('div', ':first-child')
- .attr('class', 'loader')
- .selectAll('.blockG')
- .data(d3.range(8))
- .enter()
- .append('div')
- .attr('class', function(d) {
- return 'blockG rotate' + (d + 1);
- });
- }
-
- this.wrap.attr('class', 'wc-chart');
-
- this.setDefaults();
-
- this.raw_data = data;
- this.initial_data = data;
-
- var startup = function startup(data) {
- //connect this chart and its controls, if any
- if (_this.controls) {
- _this.controls.targets.push(_this);
- if (!_this.controls.ready) {
- _this.controls.init(_this.raw_data);
- } else {
- _this.controls.layout();
- }
- }
-
- //make sure container is visible (has height and width) before trying to initialize
- var visible = d3.select(_this.div).property('offsetWidth') > 0 || test;
- if (!visible) {
- console.warn(
- 'The chart cannot be initialized inside an element with 0 width. The chart will be initialized as soon as the container element is given a width > 0.'
- );
- var onVisible = setInterval(function(i) {
- var visible_now = d3.select(_this.div).property('offsetWidth') > 0;
- if (visible_now) {
- _this.layout();
- _this.draw();
- clearInterval(onVisible);
- }
- }, 500);
- } else {
- _this.layout();
- _this.draw();
- }
- };
-
- this.events.onInit.call(this);
- if (this.raw_data.length) {
- this.checkRequired(this.raw_data);
- }
- startup(data);
-
- return this;
- }
+ var version = '1.10.0';
function checkRequired(data) {
var _this = this;
@@ -144,160 +78,6 @@
};
}
- function layout() {
- this.svg = this.wrap
- .append('svg')
- .datum(function() {
- return null;
- }) // prevent data inheritance
- .attr({
- class: 'wc-svg',
- xmlns: 'http://www.w3.org/2000/svg',
- version: '1.1',
- xlink: 'http://www.w3.org/1999/xlink'
- })
- .append('g')
- .style('display', 'inline-block');
-
- var defs = this.svg.append('defs');
- defs
- .append('pattern')
- .attr({
- id: 'diagonal-stripes',
- x: 0,
- y: 0,
- width: 3,
- height: 8,
- patternUnits: 'userSpaceOnUse',
- patternTransform: 'rotate(30)'
- })
- .append('rect')
- .attr({ x: '0', y: '0', width: '2', height: '8', style: 'stroke:none; fill:black' });
-
- defs.append('clipPath').attr('id', this.id).append('rect').attr('class', 'plotting-area');
-
- //y axis
- this.svg
- .append('g')
- .attr('class', 'y axis')
- .append('text')
- .attr('class', 'axis-title')
- .attr('transform', 'rotate(-90)')
- .attr('dy', '.75em')
- .attr('text-anchor', 'middle');
- //x axis
- this.svg
- .append('g')
- .attr('class', 'x axis')
- .append('text')
- .attr('class', 'axis-title')
- .attr('dy', '-.35em')
- .attr('text-anchor', 'middle');
- //overlay
- this.svg
- .append('rect')
- .attr('class', 'overlay')
- .attr('opacity', 0)
- .attr('fill', 'none')
- .style('pointer-events', 'all');
- //add legend
- if (!this.parent)
- this.wrap
- .append('ul')
- .datum(function() {
- return null;
- }) // prevent data inheritance
- .attr('class', 'legend')
- .style('vertical-align', 'top')
- .append('span')
- .attr('class', 'legend-title');
-
- d3.select(this.div).select('.loader').remove();
-
- this.events.onLayout.call(this);
- }
-
- function draw(raw_data, processed_data) {
- var _this = this;
-
- var chart = this;
- var config = this.config;
-
- //if pre-processing callback, run it now
- this.events.onPreprocess.call(this);
-
- /////////////////////////
- // Data prep pipeline //
- /////////////////////////
-
- // if user passed raw_data to chart.draw(), use that, otherwise use chart.raw_data
- var raw = raw_data ? raw_data : this.raw_data ? this.raw_data : [];
-
- // warn the user about the perils of "processed_data"
- if (processed_data) {
- console.warn(
- "Drawing the chart using user-defined 'processed_data', this is an experimental, untested feature."
- );
- }
-
- //Call consolidateData - this applies filters from controls and prepares data for each set of marks.
- this.consolidateData(raw);
-
- /////////////////////////////
- // Prepare scales and axes //
- /////////////////////////////
-
- var div_width = parseInt(this.wrap.style('width'));
-
- this.setColorScale();
-
- var max_width = config.max_width ? config.max_width : div_width;
- this.raw_width = config.x.type === 'ordinal' && +config.x.range_band
- ? (+config.x.range_band + config.x.range_band * config.padding) * this.x_dom.length
- : config.resizable ? max_width : config.width ? config.width : div_width;
- this.raw_height = config.y.type === 'ordinal' && +config.y.range_band
- ? (+config.y.range_band + config.y.range_band * config.padding) * this.y_dom.length
- : config.resizable
- ? max_width * (1 / config.aspect)
- : config.height ? config.height : div_width * (1 / config.aspect);
-
- var pseudo_width = this.svg.select('.overlay').attr('width')
- ? this.svg.select('.overlay').attr('width')
- : this.raw_width;
- var pseudo_height = this.svg.select('.overlay').attr('height')
- ? this.svg.select('.overlay').attr('height')
- : this.raw_height;
-
- this.svg.select('.x.axis').select('.axis-title').text(function(d) {
- return typeof config.x.label === 'string'
- ? config.x.label
- : typeof config.x.label === 'function' ? config.x.label.call(_this) : null;
- });
- this.svg.select('.y.axis').select('.axis-title').text(function(d) {
- return typeof config.y.label === 'string'
- ? config.y.label
- : typeof config.y.label === 'function' ? config.y.label.call(_this) : null;
- });
-
- this.xScaleAxis(pseudo_width);
- this.yScaleAxis(pseudo_height);
-
- if (config.resizable && typeof window !== 'undefined') {
- d3.select(window).on('resize.' + this.element + this.id, function() {
- chart.resize();
- });
- } else if (typeof window !== 'undefined') {
- d3.select(window).on('resize.' + this.element + this.id, null);
- }
-
- this.events.onDraw.call(this);
-
- //////////////////////////////////////////////////////////////////////
- // Call resize - updates marks on the chart (amongst other things) //
- /////////////////////////////////////////////////////////////////////
- this.resize();
- }
-
function naturalSorter(a, b) {
//adapted from http://www.davekoelle.com/files/alphanum.js
function chunkify(t) {
@@ -337,64 +117,80 @@
return aa.length - bb.length;
}
- function setDomain(axis) {
+ function consolidateData(raw) {
var _this = this;
- var otherAxis = axis === 'x' ? 'y' : 'x';
+ var config = this.config;
+ var all_data = [];
+ var all_x = [];
+ var all_y = [];
- if (this.config[axis].type === 'ordinal') {
- //ordinal domains
- if (this.config[axis].domain) {
- //user-defined domain
- this[axis + '_dom'] = this.config[axis].domain;
- } else if (this.config[axis].order) {
- //data-driven domain with user-defined domain order
- this[axis + '_dom'] = d3
- .set(
- d3.merge(
- this.marks.map(function(mark) {
- return mark[axis + '_dom'];
- })
- )
- )
- .values()
- .sort(function(a, b) {
- return d3.ascending(
- _this.config[axis].order.indexOf(a),
- _this.config[axis].order.indexOf(b)
- );
- });
- } else if (
- this.config[axis].sort &&
- this.config[axis].sort === 'alphabetical-ascending'
- ) {
- //data-driven domain with user-defined domain sort algorithm that sorts the axis
- //alphanumerically, first to last
- this[axis + '_dom'] = d3
- .set(
- d3.merge(
- this.marks.map(function(mark) {
- return mark[axis + '_dom'];
- })
- )
- )
- .values()
- .sort(naturalSorter);
- } else if (
- ['time', 'linear'].indexOf(this.config[otherAxis].type) > -1 &&
- this.config[axis].sort === 'earliest'
- ) {
- //data-driven domain plotted against a time or linear axis that sorts the axis values
- //by earliest event/datum; generally used with timeline charts
- this[axis + '_dom'] = d3
+ this.setDefaults();
+
+ //apply filters from associated controls objects
+ this.filtered_data = raw;
+ if (this.filters.length) {
+ this.filters.forEach(function(e) {
+ _this.filtered_data = _this.filtered_data.filter(function(d) {
+ return e.val === 'All'
+ ? d
+ : e.val instanceof Array
+ ? e.val.indexOf(d[e.col]) > -1
+ : d[e.col] === e.val;
+ });
+ });
+ }
+
+ //create data for each set of marks
+ config.marks.forEach(function(e, i) {
+ if (e.type !== 'bar') {
+ e.arrange = null;
+ e.split = null;
+ }
+ var mark_info = e.per
+ ? _this.transformData(raw, e)
+ : { data: [], x_dom: [], y_dom: [] };
+
+ all_data.push(mark_info.data);
+ all_x.push(mark_info.x_dom);
+ all_y.push(mark_info.y_dom);
+ _this.marks[i] = {
+ id: e.id,
+ type: e.type,
+ per: e.per,
+ data: mark_info.data,
+ split: e.split,
+ text: e.text,
+ arrange: e.arrange,
+ order: e.order,
+ summarizeX: e.summarizeX,
+ summarizeY: e.summarizeY,
+ tooltip: e.tooltip,
+ radius: e.radius,
+ attributes: e.attributes,
+ values: e.values
+ };
+ });
+
+ if (config.x.type === 'ordinal') {
+ if (config.x.domain) {
+ this.x_dom = config.x.domain;
+ } else if (config.x.order) {
+ this.x_dom = d3.set(d3.merge(all_x)).values().sort(function(a, b) {
+ return d3.ascending(config.x.order.indexOf(a), config.x.order.indexOf(b));
+ });
+ } else if (config.x.sort && config.x.sort === 'alphabetical-ascending') {
+ this.x_dom = d3.set(d3.merge(all_x)).values().sort(naturalSorter);
+ } else if (config.y.type === 'time' && config.x.sort === 'earliest') {
+ this.x_dom = d3
.nest()
.key(function(d) {
- return d[_this.config[axis].column];
+ return d[config.x.column];
})
.rollup(function(d) {
return d
.map(function(m) {
- return m[_this.config[otherAxis].column];
+ return m[config.y.column];
})
.filter(function(f) {
return f instanceof Date;
@@ -402,1144 +198,1202 @@
})
.entries(this.raw_data)
.sort(function(a, b) {
- return min(b.values) - min(a.values);
+ return d3.min(b.values) - d3.min(a.values);
})
.map(function(m) {
return m.key;
});
- } else if (
- !this.config[axis].sort ||
- this.config[axis].sort === 'alphabetical-descending'
- ) {
- //data-driven domain with default/user-defined domain sort algorithm that sorts the
- //axis alphanumerically, last to first
- this[axis + '_dom'] = d3
- .set(
- d3.merge(
- this.marks.map(function(mark) {
- return mark[axis + '_dom'];
- })
- )
- )
- .values()
- .sort(naturalSorter)
- .reverse();
+ } else if (!config.x.sort || config.x.sort === 'alphabetical-descending') {
+ this.x_dom = d3.set(d3.merge(all_x)).values().sort(naturalSorter);
} else {
- //data-driven domain with an invalid user-defined sort algorithm that captures a unique
- //set of values as they appear in the data
- this[axis + '_dom'] = d3
- .set(
- d3.merge(
- this.marks.map(function(mark) {
- return mark[axis + '_dom'];
- })
- )
- )
- .values();
+ this.x_dom = d3.set(d3.merge(all_x)).values();
}
} else if (
- this.config.marks
+ config.marks
.map(function(m) {
- return m['summarize' + otherAxis.toUpperCase()] === 'percent';
+ return m.summarizeX === 'percent';
})
.indexOf(true) > -1
) {
- //rate domains run from 0 to 1
- this[axis + '_dom'] = [0, 1];
+ this.x_dom = [0, 1];
} else {
- //continuous domains run from the minimum to the maximum raw value
- //TODO: they should really run from the minimum to the maximum summarized value, e.g. a
- //TODO: means over time chart should plot over the range of the means, not the range of the
- //TODO: raw data
- this[axis + '_dom'] = d3.extent(
- d3.merge(
- this.marks.map(function(mark) {
- return mark[axis + '_dom'];
- })
- )
- );
+ this.x_dom = d3.extent(d3.merge(all_x));
}
- //Give the domain a range when the range of the variable is 0.
- if (
- this.config[axis].type === 'linear' &&
- this[axis + '_dom'][0] === this[axis + '_dom'][1]
- )
- this[axis + '_dom'] = this[axis + '_dom'][0] !== 0
- ? [
- this[axis + '_dom'][0] - this[axis + '_dom'][0] * 0.01,
- this[axis + '_dom'][1] + this[axis + '_dom'][1] * 0.01
- ]
- : [-1, 1];
-
- return this[axis + '_dom'];
- }
-
- function consolidateData(raw) {
- var _this = this;
-
- this.setDefaults();
-
- //Apply filters from associated controls objects to raw data.
- this.filtered_data = raw;
- if (this.filters.length) {
- this.filters.forEach(function(filter) {
- _this.filtered_data = _this.filtered_data.filter(function(d) {
- return filter.val === 'All'
- ? d
- : filter.val instanceof Array
- ? filter.val.indexOf(d[filter.col]) > -1
- : d[filter.col] === filter.val;
+ if (config.y.type === 'ordinal') {
+ if (config.y.domain) {
+ this.y_dom = config.y.domain;
+ } else if (config.y.order) {
+ this.y_dom = d3.set(d3.merge(all_y)).values().sort(function(a, b) {
+ return d3.ascending(config.y.order.indexOf(a), config.y.order.indexOf(b));
});
- });
+ } else if (config.y.sort && config.y.sort === 'alphabetical-ascending') {
+ this.y_dom = d3.set(d3.merge(all_y)).values().sort(naturalSorter);
+ } else if (config.x.type === 'time' && config.y.sort === 'earliest') {
+ this.y_dom = d3
+ .nest()
+ .key(function(d) {
+ return d[config.y.column];
+ })
+ .rollup(function(d) {
+ return d
+ .map(function(m) {
+ return m[config.x.column];
+ })
+ .filter(function(f) {
+ return f instanceof Date;
+ });
+ })
+ .entries(this.raw_data)
+ .sort(function(a, b) {
+ return d3.min(b.values) - d3.min(a.values);
+ })
+ .map(function(m) {
+ return m.key;
+ });
+ } else if (!config.y.sort || config.y.sort === 'alphabetical-descending') {
+ this.y_dom = d3.set(d3.merge(all_y)).values().sort(naturalSorter).reverse();
+ } else {
+ this.y_dom = d3.set(d3.merge(all_y)).values();
+ }
+ } else if (
+ config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ) {
+ this.y_dom = [0, 1];
+ } else {
+ this.y_dom = d3.extent(d3.merge(all_y));
}
+ }
- //Summarize data for each mark.
- this.config.marks.forEach(function(mark, i) {
- if (mark.type !== 'bar') {
- mark.arrange = null;
- mark.split = null;
- }
+ function destroy() {
+ var destroyControls = arguments.length > 0 && arguments[0] !== undefined
+ ? arguments[0]
+ : true;
- var mark_info = mark.per
- ? _this.transformData(raw, mark)
- : {
- data: [],
- x_dom: [],
- y_dom: []
- };
+ //run onDestroy callback
+ this.events.onDestroy.call(this);
- _this.marks[i] = {
- id: mark.id,
- type: mark.type,
- per: mark.per,
- data: mark_info.data,
- x_dom: mark_info.x_dom,
- y_dom: mark_info.y_dom,
- split: mark.split,
- text: mark.text,
- arrange: mark.arrange,
- order: mark.order,
- summarizeX: mark.summarizeX,
- summarizeY: mark.summarizeY,
- tooltip: mark.tooltip,
- radius: mark.radius,
- attributes: mark.attributes,
- values: mark.values
- };
- });
+ //remove resize event listener
+ var context = this;
+ d3.select(window).on('resize.' + context.element + context.id, null);
- //Set domains given extents of summarized mark data.
- setDomain.call(this, 'x');
- setDomain.call(this, 'y');
- }
+ //destroy controls
+ if (destroyControls && this.controls) {
+ this.controls.destroy();
+ }
- function setDefaults() {
- this.config.x = this.config.x || {};
- this.config.y = this.config.y || {};
+ //unmount chart wrapper
+ this.wrap.remove();
+ }
- this.config.x.label = this.config.x.label !== undefined
- ? this.config.x.label
- : this.config.x.column;
- this.config.y.label = this.config.y.label !== undefined
- ? this.config.y.label
- : this.config.y.column;
+ function draw(raw_data, processed_data) {
+ var _this = this;
- this.config.x.sort = this.config.x.sort || 'alphabetical-ascending';
- this.config.y.sort = this.config.y.sort || 'alphabetical-descending';
+ var context = this;
+ var config = this.config;
+ var aspect2 = 1 / config.aspect;
- this.config.x.type = this.config.x.type || 'linear';
- this.config.y.type = this.config.y.type || 'linear';
+ /////////////////////////
+ // Data prep pipeline //
+ /////////////////////////
- this.config.x.range_band = this.config.x.range_band || this.config.range_band;
- this.config.y.range_band = this.config.y.range_band || this.config.range_band;
+ //if pre-processing callback, run it now
+ this.events.onPreprocess.call(this);
- this.config.margin = this.config.margin || {};
- this.config.legend = this.config.legend || {};
- this.config.legend.label = this.config.legend.label !== undefined
- ? this.config.legend.label
- : this.config.color_by;
- this.config.legend.location = this.config.legend.location !== undefined
- ? this.config.legend.location
- : 'bottom';
- this.config.marks = this.config.marks && this.config.marks.length
- ? this.config.marks
- : [{}];
- this.config.marks.forEach(function(m, i) {
- m.id = m.id ? m.id : 'mark' + (i + 1);
- });
+ // if user passed raw_data to chart.draw(), use that, otherwise use chart.raw_data
+ var raw = raw_data ? raw_data : this.raw_data ? this.raw_data : [];
- this.config.date_format = this.config.date_format || '%x';
+ // warn the user about the perils of "processed_data"
+ if (processed_data) {
+ console.warn(
+ "Drawing the chart using user-defined 'processed_data', this is an experimental, untested feature."
+ );
+ }
- this.config.padding = this.config.padding !== undefined ? this.config.padding : 0.3;
- this.config.outer_pad = this.config.outer_pad !== undefined ? this.config.outer_pad : 0.1;
+ //Call consolidateData - this applies filters from controls and prepares data for each set of marks.
+ var data = processed_data || this.consolidateData(raw);
- this.config.resizable = this.config.resizable !== undefined ? this.config.resizable : true;
+ /////////////////////////////
+ // Prepare scales and axes //
+ /////////////////////////////
- this.config.aspect = this.config.aspect || 1.33;
+ var div_width = parseInt(this.wrap.style('width'));
- this.config.colors = this.config.colors || [
- 'rgb(102,194,165)',
- 'rgb(252,141,98)',
- 'rgb(141,160,203)',
- 'rgb(231,138,195)',
- 'rgb(166,216,84)',
- 'rgb(255,217,47)',
- 'rgb(229,196,148)',
- 'rgb(179,179,179)'
- ];
+ this.setColorScale();
- this.config.scale_text = this.config.scale_text === undefined
- ? true
- : this.config.scale_text;
- this.config.transitions = this.config.transitions === undefined
- ? true
- : this.config.transitions;
- }
+ var max_width = config.max_width ? config.max_width : div_width;
+ this.raw_width = config.x.type === 'ordinal' && +config.range_band
+ ? (+config.range_band + config.range_band * config.padding) * this.x_dom.length
+ : config.resizable ? max_width : config.width ? config.width : div_width;
+ this.raw_height = config.y.type === 'ordinal' && +config.range_band
+ ? (+config.range_band + config.range_band * config.padding) * this.y_dom.length
+ : config.resizable
+ ? max_width * aspect2
+ : config.height ? config.height : div_width * aspect2;
- function cleanData(mark, raw) {
- var _this = this;
+ var pseudo_width = this.svg.select('.overlay').attr('width')
+ ? this.svg.select('.overlay').attr('width')
+ : this.raw_width;
+ var pseudo_height = this.svg.select('.overlay').attr('height')
+ ? this.svg.select('.overlay').attr('height')
+ : this.raw_height;
- var dateConvert = d3.time.format(this.config.date_format);
- var clean = raw;
- // only use data for the current mark
- clean = mark.per && mark.per.length
- ? clean.filter(function(f) {
- return f[mark.per[0]] !== undefined;
- })
- : clean;
+ this.svg.select('.x.axis').select('.axis-title').text(function(d) {
+ return typeof config.x.label === 'string'
+ ? config.x.label
+ : typeof config.x.label === 'function' ? config.x.label.call(_this) : null;
+ });
+ this.svg.select('.y.axis').select('.axis-title').text(function(d) {
+ return typeof config.y.label === 'string'
+ ? config.y.label
+ : typeof config.y.label === 'function' ? config.y.label.call(_this) : null;
+ });
- // Make sure data has x and y values
- if (this.config.x.column) {
- clean = clean.filter(function(f) {
- return [undefined, null].indexOf(f[_this.config.x.column]) < 0;
- });
- }
- if (this.config.y.column) {
- clean = clean.filter(function(f) {
- return [undefined, null].indexOf(f[_this.config.y.column]) < 0;
- });
- }
+ this.xScaleAxis(pseudo_width);
+ this.yScaleAxis(pseudo_height);
- //check that x and y have the correct formats
- if (this.config.x.type === 'time') {
- clean = clean.filter(function(f) {
- return f[_this.config.x.column] instanceof Date
- ? f[_this.config.x.column]
- : dateConvert.parse(f[_this.config.x.column]);
- });
- clean.forEach(function(e) {
- return (e[_this.config.x.column] = e[_this.config.x.column] instanceof Date
- ? e[_this.config.x.column]
- : dateConvert.parse(e[_this.config.x.column]));
- });
- }
- if (this.config.y.type === 'time') {
- clean = clean.filter(function(f) {
- return f[_this.config.y.column] instanceof Date
- ? f[_this.config.y.column]
- : dateConvert.parse(f[_this.config.y.column]);
- });
- clean.forEach(function(e) {
- return (e[_this.config.y.column] = e[_this.config.y.column] instanceof Date
- ? e[_this.config.y.column]
- : dateConvert.parse(e[_this.config.y.column]));
+ if (config.resizable && typeof window !== 'undefined') {
+ d3.select(window).on('resize.' + context.element + context.id, function() {
+ context.resize();
});
+ } else if (typeof window !== 'undefined') {
+ d3.select(window).on('resize.' + context.element + context.id, null);
}
- if (
- (this.config.x.type === 'linear' || this.config.x.type === 'log') &&
- this.config.x.column
- ) {
- clean = clean.filter(function(f) {
- return mark.summarizeX !== 'count' && mark.summarizeX !== 'percent'
- ? !(isNaN(f[_this.config.x.column]) || /^\s*$/.test(f[_this.config.x.column])) // is or coerces to a number and is not a string that coerces to 0
- : f;
- });
- }
- if (
- (this.config.y.type === 'linear' || this.config.y.type === 'log') &&
- this.config.y.column
- ) {
- clean = clean.filter(function(f) {
- return mark.summarizeY !== 'count' && mark.summarizeY !== 'percent'
- ? !(isNaN(f[_this.config.y.column]) || /^\s*$/.test(f[_this.config.y.column])) // is or coerces to a number and is not a string that coerces to 0
- : f;
- });
- }
+ this.events.onDraw.call(this);
- return clean;
+ //////////////////////////////////////////////////////////////////////
+ // Call resize - updates marks on the chart (amongst other things) //
+ /////////////////////////////////////////////////////////////////////
+ this.resize();
}
- var stats = {
- mean: d3.mean,
- min: d3.min,
- max: d3.max,
- median: d3.median,
- sum: d3.sum
- };
+ function drawArea(area_drawer, area_data, datum_accessor) {
+ var class_match = arguments.length > 3 && arguments[3] !== undefined
+ ? arguments[3]
+ : 'chart-area';
- function summarize(vals) {
- var operation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'mean';
+ var _this = this;
- var nvals = vals
- .filter(function(f) {
- return +f || +f === 0;
+ var bind_accessor = arguments[4];
+ var attr_accessor = arguments.length > 5 && arguments[5] !== undefined
+ ? arguments[5]
+ : function(d) {
+ return d;
+ };
+
+ var area_grps = this.svg.selectAll('.' + class_match).data(area_data, bind_accessor);
+ area_grps.exit().remove();
+ area_grps
+ .enter()
+ .append('g')
+ .attr('class', function(d) {
+ return class_match + ' ' + d.key;
})
- .map(function(m) {
- return +m;
- });
+ .append('path');
- if (operation === 'cumulative') {
- return null;
- }
+ var areaPaths = area_grps
+ .select('path')
+ .datum(datum_accessor)
+ .attr('fill', function(d) {
+ var d_attr = attr_accessor(d);
+ return d_attr ? _this.colorScale(d_attr[_this.config.color_by]) : null;
+ })
+ .attr(
+ 'fill-opacity',
+ this.config.fill_opacity || this.config.fill_opacity === 0
+ ? this.config.fill_opacity
+ : 0.3
+ );
- var mathed = operation === 'count'
- ? vals.length
- : operation === 'percent' ? vals.length : stats[operation](nvals);
+ //don't transition if config says not to
+ var areaPathTransitions = this.config.transitions ? areaPaths.transition() : areaPaths;
- return mathed;
+ areaPathTransitions.attr('d', area_drawer);
+
+ return area_grps;
}
- function makeNest(mark, entries, sublevel) {
+ function drawBars(marks) {
var _this = this;
- var dom_xs = [];
- var dom_ys = [];
- var this_nest = d3.nest();
- var totalOrder = void 0;
+ var rawData = this.raw_data;
+ var config = this.config;
- if (
- (this.config.x.type === 'linear' && this.config.x.bin) ||
- (this.config.y.type === 'linear' && this.config.y.bin)
- ) {
- var xy = this.config.x.type === 'linear' && this.config.x.bin ? 'x' : 'y';
- var quant = d3.scale
- .quantile()
- .domain(
- d3.extent(
- entries.map(function(m) {
- return +m[_this.config[xy].column];
- })
- )
- )
- .range(d3.range(+this.config[xy].bin));
-
- entries.forEach(function(e) {
- return (e.wc_bin = quant(e[_this.config[xy].column]));
- });
+ var bar_supergroups = this.svg.selectAll('.bar-supergroup').data(marks, function(d, i) {
+ return i + '-' + d.per.join('-');
+ });
- this_nest.key(function(d) {
- return quant.invertExtent(d.wc_bin);
- });
- } else {
- this_nest.key(function(d) {
- return mark.per
- .map(function(m) {
- return d[m];
- })
- .join(' ');
- });
- }
+ bar_supergroups.enter().append('g').attr('class', function(d) {
+ return 'supergroup bar-supergroup ' + d.id;
+ });
- if (sublevel) {
- this_nest.key(function(d) {
- return d[sublevel];
- });
- this_nest.sortKeys(function(a, b) {
- return _this.config.x.type === 'time'
- ? d3.ascending(new Date(a), new Date(b))
- : _this.config.x.order
- ? d3.ascending(
- _this.config.x.order.indexOf(a),
- _this.config.x.order.indexOf(b)
- )
- : sublevel === _this.config.color_by && _this.config.legend.order
- ? d3.ascending(
- _this.config.legend.order.indexOf(a),
- _this.config.legend.order.indexOf(b)
- )
- : _this.config.x.type === 'ordinal' || _this.config.y.type === 'ordinal'
- ? naturalSorter(a, b)
- : d3.ascending(+a, +b);
- });
- }
- this_nest.rollup(function(r) {
- var obj = { raw: r };
- var y_vals = r
- .map(function(m) {
- return m[_this.config.y.column];
- })
- .sort(d3.ascending);
- var x_vals = r
- .map(function(m) {
- return m[_this.config.x.column];
- })
- .sort(d3.ascending);
- obj.x = _this.config.x.type === 'ordinal'
- ? r[0][_this.config.x.column]
- : summarize(x_vals, mark.summarizeX);
- obj.y = _this.config.y.type === 'ordinal'
- ? r[0][_this.config.y.column]
- : summarize(y_vals, mark.summarizeY);
-
- obj.x_q25 = _this.config.error_bars && _this.config.y.type === 'ordinal'
- ? d3.quantile(x_vals, 0.25)
- : obj.x;
- obj.x_q75 = _this.config.error_bars && _this.config.y.type === 'ordinal'
- ? d3.quantile(x_vals, 0.75)
- : obj.x;
- obj.y_q25 = _this.config.error_bars ? d3.quantile(y_vals, 0.25) : obj.y;
- obj.y_q75 = _this.config.error_bars ? d3.quantile(y_vals, 0.75) : obj.y;
- dom_xs.push([obj.x_q25, obj.x_q75, obj.x]);
- dom_ys.push([obj.y_q25, obj.y_q75, obj.y]);
-
- if (mark.summarizeY === 'cumulative') {
- var interm = entries.filter(function(f) {
- return _this.config.x.type === 'time'
- ? new Date(f[_this.config.x.column]) <=
- new Date(r[0][_this.config.x.column])
- : +f[_this.config.x.column] <= +r[0][_this.config.x.column];
- });
- if (mark.per.length) {
- interm = interm.filter(function(f) {
- return f[mark.per[0]] === r[0][mark.per[0]];
- });
- }
+ bar_supergroups.exit().remove();
- var cumul = _this.config.x.type === 'time'
- ? interm.length
- : d3.sum(
- interm.map(function(m) {
- return +m[_this.config.y.column] || +m[_this.config.y.column] === 0
- ? +m[_this.config.y.column]
- : 1;
- })
- );
- dom_ys.push([cumul]);
- obj.y = cumul;
- }
- if (mark.summarizeX === 'cumulative') {
- var _interm = entries.filter(function(f) {
- return _this.config.y.type === 'time'
- ? new Date(f[_this.config.y.column]) <=
- new Date(r[0][_this.config.y.column])
- : +f[_this.config.y.column] <= +r[0][_this.config.y.column];
- });
- if (mark.per.length) {
- _interm = _interm.filter(function(f) {
- return f[mark.per[0]] === r[0][mark.per[0]];
- });
- }
- dom_xs.push([_interm.length]);
- obj.x = _interm.length;
+ var bar_groups = bar_supergroups.selectAll('.bar-group').data(
+ function(d) {
+ return d.data;
+ },
+ function(d) {
+ return d.key;
}
+ );
+ var old_bar_groups = bar_groups.exit();
- return obj;
- });
+ var nu_bar_groups = void 0;
+ var bars = void 0;
+
+ var oldBarsTrans = config.transitions
+ ? old_bar_groups.selectAll('.bar').transition()
+ : old_bar_groups.selectAll('.bar');
+ var oldBarGroupsTrans = config.transitions ? old_bar_groups.transition() : old_bar_groups;
- var test = this_nest.entries(entries);
+ if (config.x.type === 'ordinal') {
+ oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
- var dom_x = d3.extent(d3.merge(dom_xs));
- var dom_y = d3.extent(d3.merge(dom_ys));
+ oldBarGroupsTrans.remove();
- if (sublevel && mark.type === 'bar' && mark.split) {
- //calculate percentages in bars
- test.forEach(function(e) {
- var axis = _this.config.x.type === 'ordinal' ||
- (_this.config.x.type === 'linear' && _this.config.x.bin)
- ? 'y'
- : 'x';
- e.total = d3.sum(
- e.values.map(function(m) {
- return +m.values[axis];
- })
- );
- var counter = 0;
- e.values.forEach(function(v, i) {
- if (
- _this.config.x.type === 'ordinal' ||
- (_this.config.x.type === 'linear' && _this.config.x.bin)
- ) {
- v.values.y = mark.summarizeY === 'percent'
- ? v.values.y / e.total
- : v.values.y || 0;
- counter += +v.values.y;
- v.values.start = e.values[i - 1] ? counter : v.values.y;
- } else {
- v.values.x = mark.summarizeX === 'percent'
- ? v.values.x / e.total
- : v.values.x || 0;
- v.values.start = counter;
- counter += +v.values.x;
- }
- });
+ nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
+ return 'bar-group ' + d.key;
});
+ nu_bar_groups.append('title');
- if (mark.arrange === 'stacked') {
- if (
- this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ) {
- dom_y = d3.extent(
- test.map(function(m) {
- return m.total;
- })
- );
- }
- if (
- this.config.y.type === 'ordinal' ||
- (this.config.y.type === 'linear' && this.config.y.bin)
- ) {
- dom_x = d3.extent(
- test.map(function(m) {
- return m.total;
- })
- );
+ bars = bar_groups.selectAll('rect').data(
+ function(d) {
+ return d.values instanceof Array
+ ? d.values.sort(function(a, b) {
+ return (
+ _this.colorScale.domain().indexOf(b.key) -
+ _this.colorScale.domain().indexOf(a.key)
+ );
+ })
+ : [d];
+ },
+ function(d) {
+ return d.key;
}
- }
- } else {
- var axis = this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ? 'y'
- : 'x';
- test.forEach(function(e) {
- return (e.total = e.values[axis]);
- });
- }
+ );
- if (
- (this.config.x.sort === 'total-ascending' && this.config.x.type == 'ordinal') ||
- (this.config.y.sort === 'total-descending' && this.config.y.type == 'ordinal')
- ) {
- totalOrder = test
- .sort(function(a, b) {
- return d3.ascending(a.total, b.total);
+ var exitBars = config.transitions ? bars.exit().transition() : bars.exit();
+ exitBars.attr('y', this.y(0)).attr('height', 0).remove();
+ bars
+ .enter()
+ .append('rect')
+ .attr('class', function(d) {
+ return 'wc-data-mark bar ' + d.key;
})
- .map(function(m) {
- return m.key;
- });
- } else if (
- (this.config.x.sort === 'total-descending' && this.config.x.type == 'ordinal') ||
- (this.config.y.sort === 'total-ascending' && this.config.y.type == 'ordinal')
- ) {
- totalOrder = test
- .sort(function(a, b) {
- return d3.descending(+a.total, +b.total);
+ .style('clip-path', 'url(#' + this.id + ')')
+ .attr('y', this.y(0))
+ .attr('height', 0)
+ .append('title');
+
+ bars
+ .attr('shape-rendering', 'crispEdges')
+ .attr('stroke', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
})
- .map(function(m) {
- return m.key;
+ .attr('fill', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
});
- }
- return { nested: test, dom_x: dom_x, dom_y: dom_y, totalOrder: totalOrder };
- }
+ bars.each(function(d) {
+ var mark = d3.select(this.parentNode.parentNode).datum();
+ d.tooltip = mark.tooltip;
+ d.arrange = mark.split ? mark.arrange : null;
+ d.subcats = config.legend.order
+ ? config.legend.order.slice().reverse()
+ : mark.values && mark.values[mark.split]
+ ? mark.values[mark.split]
+ : d3
+ .set(
+ rawData.map(function(m) {
+ return m[mark.split];
+ })
+ )
+ .values();
+ d3.select(this).attr(mark.attributes);
+ });
- //////////////////////////////////////////////////////////
- // transformData(raw, mark) provides specifications and data for
- // each set of marks. As such, it is called once for each
- // item specified in the config.marks array.
- //
- // parameters
- // raw - the raw data for use in the mark. Filters from controls
- // are typically already applied.
- // mark - a single mark object from config.marks
- ////////////////////////////////////////////////////////
+ var xformat = config.marks
+ .map(function(m) {
+ return m.summarizeX === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.x.format);
+ var yformat = config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.y.format);
+ bars.select('title').text(function(d) {
+ var tt = d.tooltip || '';
+ return tt
+ .replace(/\$x/g, xformat(d.values.x))
+ .replace(/\$y/g, yformat(d.values.y))
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
+ });
+ });
- function transformData(raw, mark) {
- var _this = this;
+ var barsTrans = config.transitions ? bars.transition() : bars;
+ barsTrans
+ .attr('x', function(d) {
+ var position = void 0;
+ if (!d.arrange || d.arrange === 'stacked') {
+ return _this.x(d.values.x);
+ } else if (d.arrange === 'nested') {
+ var _position = d.subcats.indexOf(d.key);
+ var offset = _position
+ ? _this.x.rangeBand() / (d.subcats.length * 0.75) / _position
+ : _this.x.rangeBand();
+ return _this.x(d.values.x) + (_this.x.rangeBand() - offset) / 2;
+ } else {
+ position = d.subcats.indexOf(d.key);
+ return (
+ _this.x(d.values.x) + _this.x.rangeBand() / d.subcats.length * position
+ );
+ }
+ })
+ .attr('y', function(d) {
+ if (d.arrange !== 'stacked') {
+ return _this.y(d.values.y);
+ } else {
+ return _this.y(d.values.start);
+ }
+ })
+ .attr('width', function(d) {
+ if (!d.arrange || d.arrange === 'stacked') {
+ return _this.x.rangeBand();
+ } else if (d.arrange === 'nested') {
+ var position = d.subcats.indexOf(d.key);
+ return position
+ ? _this.x.rangeBand() / (d.subcats.length * 0.75) / position
+ : _this.x.rangeBand();
+ } else {
+ return _this.x.rangeBand() / d.subcats.length;
+ }
+ })
+ .attr('height', function(d) {
+ return _this.y(0) - _this.y(d.values.y);
+ });
+ } else if (config.y.type === 'ordinal') {
+ oldBarsTrans.attr('x', this.x(0)).attr('width', 0);
- //convenience mappings
- var config = this.config;
- var x_behavior = config.x.behavior || 'raw';
- var y_behavior = config.y.behavior || 'raw';
- var sublevel = mark.type === 'line'
- ? config.x.column
- : mark.type === 'bar' && mark.split ? mark.split : null;
+ oldBarGroupsTrans.remove();
- //////////////////////////////////////////////////////////////////////////////////
- // DATA PREP
- // prepare data based on the properties of the mark - drop missing records, etc
- //////////////////////////////////////////////////////////////////////////////////
- var cleaned = cleanData.call(this, mark, raw);
+ nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
+ return 'bar-group ' + d.key;
+ });
+ nu_bar_groups.append('title');
- //prepare nested data required for bar charts
- var raw_nest = void 0;
- if (mark.type === 'bar') {
- raw_nest = mark.arrange !== 'stacked'
- ? makeNest.call(this, mark, cleaned, sublevel)
- : makeNest.call(this, mark, cleaned);
- } else if (mark.summarizeX === 'count' || mark.summarizeY === 'count') {
- raw_nest = makeNest.call(this, mark, cleaned);
- }
+ bars = bar_groups.selectAll('rect').data(
+ function(d) {
+ return d.values instanceof Array
+ ? d.values.sort(function(a, b) {
+ return (
+ _this.colorScale.domain().indexOf(b.key) -
+ _this.colorScale.domain().indexOf(a.key)
+ );
+ })
+ : [d];
+ },
+ function(d) {
+ return d.key;
+ }
+ );
- // Get the domain for the mark based on the raw data
- var raw_dom_x = mark.summarizeX === 'cumulative'
- ? [0, cleaned.length]
- : config.x.type === 'ordinal'
- ? d3
- .set(
- cleaned.map(function(m) {
- return m[config.x.column];
- })
- )
- .values()
- .filter(function(f) {
- return f;
- })
- : mark.split && mark.arrange !== 'stacked'
- ? d3.extent(
- d3.merge(
- raw_nest.nested.map(function(m) {
- return m.values.map(function(p) {
- return p.values.raw.length;
- });
- })
- )
- )
- : mark.summarizeX === 'count'
- ? d3.extent(
- raw_nest.nested.map(function(m) {
- return m.values.raw.length;
- })
- )
- : d3.extent(
- cleaned
- .map(function(m) {
- return +m[config.x.column];
- })
- .filter(function(f) {
- return +f || +f === 0;
- })
- );
+ var _exitBars = config.transitions ? bars.exit().transition() : bars.exit();
+ _exitBars.attr('x', this.x(0)).attr('width', 0).remove();
+ bars
+ .enter()
+ .append('rect')
+ .attr('class', function(d) {
+ return 'wc-data-mark bar ' + d.key;
+ })
+ .style('clip-path', 'url(#' + this.id + ')')
+ .attr('x', this.x(0))
+ .attr('width', 0)
+ .append('title');
- var raw_dom_y = mark.summarizeY === 'cumulative'
- ? [0, cleaned.length]
- : config.y.type === 'ordinal'
- ? d3
- .set(
- cleaned.map(function(m) {
- return m[config.y.column];
- })
- )
- .values()
- .filter(function(f) {
- return f;
- })
- : mark.split && mark.arrange !== 'stacked'
- ? d3.extent(
- d3.merge(
- raw_nest.nested.map(function(m) {
- return m.values.map(function(p) {
- return p.values.raw.length;
- });
- })
- )
- )
- : mark.summarizeY === 'count'
- ? d3.extent(
- raw_nest.nested.map(function(m) {
- return m.values.raw.length;
- })
- )
- : d3.extent(
- cleaned
- .map(function(m) {
- return +m[config.y.column];
- })
- .filter(function(f) {
- return +f || +f === 0;
- })
- );
+ bars
+ .attr('shape-rendering', 'crispEdges')
+ .attr('stroke', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ })
+ .attr('fill', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ });
+
+ bars.each(function(d) {
+ var mark = d3.select(this.parentNode.parentNode).datum();
+ d.arrange = mark.split && mark.arrange
+ ? mark.arrange
+ : mark.split ? 'grouped' : null;
+ d.subcats = config.legend.order
+ ? config.legend.order.slice().reverse()
+ : mark.values && mark.values[mark.split]
+ ? mark.values[mark.split]
+ : d3
+ .set(
+ rawData.map(function(m) {
+ return m[mark.split];
+ })
+ )
+ .values();
+ d.tooltip = mark.tooltip;
+ });
+
+ var _xformat = config.marks
+ .map(function(m) {
+ return m.summarizeX === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.x.format);
+ var _yformat = config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.y.format);
+ bars.select('title').text(function(d) {
+ var tt = d.tooltip || '';
+ return tt
+ .replace(/\$x/g, _xformat(d.values.x))
+ .replace(/\$y/g, _yformat(d.values.y))
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
+ });
+ });
+
+ var _barsTrans = config.transitions ? bars.transition() : bars;
+ _barsTrans
+ .attr('x', function(d) {
+ if (d.arrange === 'stacked' || !d.arrange) {
+ return d.values.start !== undefined ? _this.x(d.values.start) : _this.x(0);
+ } else {
+ return _this.x(0);
+ }
+ })
+ .attr('y', function(d) {
+ if (d.arrange === 'nested') {
+ var position = d.subcats.indexOf(d.key);
+ var offset = position
+ ? _this.y.rangeBand() / (d.subcats.length * 0.75) / position
+ : _this.y.rangeBand();
+ return _this.y(d.values.y) + (_this.y.rangeBand() - offset) / 2;
+ } else if (d.arrange === 'grouped') {
+ var _position2 = d.subcats.indexOf(d.key);
+ return (
+ _this.y(d.values.y) +
+ _this.y.rangeBand() / d.subcats.length * _position2
+ );
+ } else {
+ return _this.y(d.values.y);
+ }
+ })
+ .attr('width', function(d) {
+ return _this.x(d.values.x) - _this.x(0);
+ })
+ .attr('height', function(d) {
+ if (config.y.type === 'quantile') {
+ return 20;
+ } else if (d.arrange === 'nested') {
+ var position = d.subcats.indexOf(d.key);
+ return position
+ ? _this.y.rangeBand() / (d.subcats.length * 0.75) / position
+ : _this.y.rangeBand();
+ } else if (d.arrange === 'grouped') {
+ return _this.y.rangeBand() / d.subcats.length;
+ } else {
+ return _this.y.rangeBand();
+ }
+ });
+ } else if (['linear', 'log'].indexOf(config.x.type) > -1 && config.x.bin) {
+ oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
+
+ oldBarGroupsTrans.remove();
+
+ nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
+ return 'bar-group ' + d.key;
+ });
+ nu_bar_groups.append('title');
+
+ bars = bar_groups.selectAll('rect').data(
+ function(d) {
+ return d.values instanceof Array ? d.values : [d];
+ },
+ function(d) {
+ return d.key;
+ }
+ );
+
+ var _exitBars2 = config.transitions ? bars.exit().transition() : bars.exit();
+ _exitBars2.attr('y', this.y(0)).attr('height', 0).remove();
+ bars
+ .enter()
+ .append('rect')
+ .attr('class', function(d) {
+ return 'wc-data-mark bar ' + d.key;
+ })
+ .style('clip-path', 'url(#' + this.id + ')')
+ .attr('y', this.y(0))
+ .attr('height', 0)
+ .append('title');
+
+ bars
+ .attr('shape-rendering', 'crispEdges')
+ .attr('stroke', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ })
+ .attr('fill', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ });
+
+ bars.each(function(d) {
+ var mark = d3.select(this.parentNode.parentNode).datum();
+ d.arrange = mark.split ? mark.arrange : null;
+ d.subcats = config.legend.order
+ ? config.legend.order.slice().reverse()
+ : mark.values && mark.values[mark.split]
+ ? mark.values[mark.split]
+ : d3
+ .set(
+ rawData.map(function(m) {
+ return m[mark.split];
+ })
+ )
+ .values();
+ d3.select(this).attr(mark.attributes);
+ var parent = d3.select(this.parentNode).datum();
+ var rangeSet = parent.key.split(',').map(function(m) {
+ return +m;
+ });
+ d.rangeLow = d3.min(rangeSet);
+ d.rangeHigh = d3.max(rangeSet);
+ d.tooltip = mark.tooltip;
+ });
+
+ var _xformat2 = config.marks
+ .map(function(m) {
+ return m.summarizeX === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.x.format);
+ var _yformat2 = config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.y.format);
+ bars.select('title').text(function(d) {
+ var tt = d.tooltip || '';
+ return tt
+ .replace(/\$x/g, _xformat2(d.values.x))
+ .replace(/\$y/g, _yformat2(d.values.y))
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
+ });
+ });
+
+ var _barsTrans2 = config.transitions ? bars.transition() : bars;
+ _barsTrans2
+ .attr('x', function(d) {
+ return _this.x(d.rangeLow);
+ })
+ .attr('y', function(d) {
+ if (d.arrange !== 'stacked') {
+ return _this.y(d.values.y);
+ } else {
+ return _this.y(d.values.start);
+ }
+ })
+ .attr('width', function(d) {
+ return _this.x(d.rangeHigh) - _this.x(d.rangeLow);
+ })
+ .attr('height', function(d) {
+ return _this.y(0) - _this.y(d.values.y);
+ });
+ } else if (
+ ['linear', 'log'].indexOf(config.y.type) > -1 &&
+ config.y.type === 'linear' &&
+ config.y.bin
+ ) {
+ oldBarsTrans.attr('x', this.x(0)).attr('width', 0);
+ oldBarGroupsTrans.remove();
+
+ nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
+ return 'bar-group ' + d.key;
+ });
+ nu_bar_groups.append('title');
+
+ bars = bar_groups.selectAll('rect').data(
+ function(d) {
+ return d.values instanceof Array ? d.values : [d];
+ },
+ function(d) {
+ return d.key;
+ }
+ );
+
+ var _exitBars3 = config.transitions ? bars.exit().transition() : bars.exit();
+ _exitBars3.attr('x', this.x(0)).attr('width', 0).remove();
+ bars
+ .enter()
+ .append('rect')
+ .attr('class', function(d) {
+ return 'wc-data-mark bar ' + d.key;
+ })
+ .style('clip-path', 'url(#' + this.id + ')')
+ .attr('x', this.x(0))
+ .attr('width', 0)
+ .append('title');
- var filtered = cleaned;
+ bars
+ .attr('shape-rendering', 'crispEdges')
+ .attr('stroke', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ })
+ .attr('fill', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ });
- var filt1_xs = [];
- var filt1_ys = [];
- if (this.filters.length) {
- this.filters.forEach(function(e) {
- filtered = filtered.filter(function(d) {
- return e.val === 'All'
- ? d
- : e.val instanceof Array
- ? e.val.indexOf(d[e.col]) > -1
- : d[e.col] === e.val;
+ bars.each(function(d) {
+ var mark = d3.select(this.parentNode.parentNode).datum();
+ d.arrange = mark.split ? mark.arrange : null;
+ d.subcats = config.legend.order
+ ? config.legend.order.slice().reverse()
+ : mark.values && mark.values[mark.split]
+ ? mark.values[mark.split]
+ : d3
+ .set(
+ rawData.map(function(m) {
+ return m[mark.split];
+ })
+ )
+ .values();
+ var parent = d3.select(this.parentNode).datum();
+ var rangeSet = parent.key.split(',').map(function(m) {
+ return +m;
});
+ d.rangeLow = d3.min(rangeSet);
+ d.rangeHigh = d3.max(rangeSet);
+ d.tooltip = mark.tooltip;
});
- //get domain for all non-All values of first filter
- if (config.x.behavior === 'firstfilter' || config.y.behavior === 'firstfilter') {
- this.filters[0].choices
- .filter(function(f) {
- return f !== 'All';
- })
- .forEach(function(e) {
- var perfilter = cleaned.filter(function(f) {
- return f[_this.filters[0].col] === e;
- });
- var filt_nested = makeNest.call(_this, mark, perfilter, sublevel);
- filt1_xs.push(filt_nested.dom_x);
- filt1_ys.push(filt_nested.dom_y);
+
+ var _xformat3 = config.marks
+ .map(function(m) {
+ return m.summarizeX === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.x.format);
+ var _yformat3 = config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ? d3.format('0%')
+ : d3.format(config.y.format);
+ bars.select('title').text(function(d) {
+ var tt = d.tooltip || '';
+ return tt
+ .replace(/\$x/g, _xformat3(d.values.x))
+ .replace(/\$y/g, _yformat3(d.values.y))
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
});
- }
- }
+ });
- //filter on mark-specific instructions
- if (mark.values) {
- var _loop = function _loop(a) {
- filtered = filtered.filter(function(f) {
- return mark.values[a].indexOf(f[a]) > -1;
+ var _barsTrans3 = config.transitions ? bars.transition() : bars;
+ _barsTrans3
+ .attr('x', function(d) {
+ if (d.arrange === 'stacked') {
+ return _this.x(d.values.start);
+ } else {
+ return _this.x(0);
+ }
+ })
+ .attr('y', function(d) {
+ return _this.y(d.rangeHigh);
+ })
+ .attr('width', function(d) {
+ return _this.x(d.values.x);
+ })
+ .attr('height', function(d) {
+ return _this.y(d.rangeLow) - _this.y(d.rangeHigh);
});
- };
-
- for (var a in mark.values) {
- _loop(a);
- }
+ } else {
+ oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
+ oldBarGroupsTrans.remove();
+ bar_supergroups.remove();
}
- var filt1_dom_x = d3.extent(d3.merge(filt1_xs));
- var filt1_dom_y = d3.extent(d3.merge(filt1_ys));
-
- var current_nested = makeNest.call(this, mark, filtered, sublevel);
- var flex_dom_x = current_nested.dom_x;
- var flex_dom_y = current_nested.dom_y;
+ //Link to the d3.selection from the data
+ bar_supergroups.each(function(d) {
+ d.supergroup = d3.select(this);
+ d.groups = d.supergroup.selectAll('.bar-group');
+ });
+ }
- if (mark.type === 'bar') {
- if (config.y.type === 'ordinal' && mark.summarizeX === 'count') {
- config.x.domain = config.x.domain ? [0, config.x.domain[1]] : [0, null];
- } else if (config.x.type === 'ordinal' && mark.summarizeY === 'count') {
- config.y.domain = config.y.domain ? [0, config.y.domain[1]] : [0, null];
- }
+ function drawGridLines() {
+ this.wrap.classed('gridlines', this.config.gridlines);
+ if (this.config.gridlines) {
+ this.svg.select('.y.axis').selectAll('.tick line').attr('x1', 0);
+ this.svg.select('.x.axis').selectAll('.tick line').attr('y1', 0);
+ if (this.config.gridlines === 'y' || this.config.gridlines === 'xy')
+ this.svg.select('.y.axis').selectAll('.tick line').attr('x1', this.plot_width);
+ if (this.config.gridlines === 'x' || this.config.gridlines === 'xy')
+ this.svg.select('.x.axis').selectAll('.tick line').attr('y1', -this.plot_height);
+ } else {
+ this.svg.select('.y.axis').selectAll('.tick line').attr('x1', 0);
+ this.svg.select('.x.axis').selectAll('.tick line').attr('y1', 0);
}
+ }
- //several criteria must be met in order to use the 'firstfilter' domain
- var nonall = Boolean(
- this.filters.length &&
- this.filters[0].val !== 'All' &&
- this.filters.slice(1).filter(function(f) {
- return f.val === 'All';
- }).length ===
- this.filters.length - 1
- );
-
- var pre_x_dom = !this.filters.length
- ? flex_dom_x
- : x_behavior === 'raw'
- ? raw_dom_x
- : nonall && x_behavior === 'firstfilter' ? filt1_dom_x : flex_dom_x;
- var pre_y_dom = !this.filters.length
- ? flex_dom_y
- : y_behavior === 'raw'
- ? raw_dom_y
- : nonall && y_behavior === 'firstfilter' ? filt1_dom_y : flex_dom_y;
+ function drawLines(marks) {
+ var _this = this;
- var x_dom = config.x_dom
- ? config.x_dom
- : config.x.type === 'ordinal' && config.x.behavior === 'flex'
- ? d3
- .set(
- filtered.map(function(m) {
- return m[config.x.column];
- })
- )
- .values()
- : config.x.type === 'ordinal'
- ? d3
- .set(
- cleaned.map(function(m) {
- return m[config.x.column];
- })
- )
- .values()
- : pre_x_dom;
+ var config = this.config;
+ var line = d3.svg
+ .line()
+ .interpolate(config.interpolate)
+ .x(function(d) {
+ return config.x.type === 'linear' || config.x.type == 'log'
+ ? _this.x(+d.values.x)
+ : config.x.type === 'time'
+ ? _this.x(new Date(d.values.x))
+ : _this.x(d.values.x) + _this.x.rangeBand() / 2;
+ })
+ .y(function(d) {
+ return config.y.type === 'linear' || config.y.type == 'log'
+ ? _this.y(+d.values.y)
+ : config.y.type === 'time'
+ ? _this.y(new Date(d.values.y))
+ : _this.y(d.values.y) + _this.y.rangeBand() / 2;
+ });
- var y_dom = config.y_dom
- ? config.y_dom
- : config.y.type === 'ordinal' && config.y.behavior === 'flex'
- ? d3
- .set(
- filtered.map(function(m) {
- return m[config.y.column];
- })
- )
- .values()
- : config.y.type === 'ordinal'
- ? d3
- .set(
- cleaned.map(function(m) {
- return m[config.y.column];
- })
- )
- .values()
- : pre_y_dom;
+ var line_supergroups = this.svg.selectAll('.line-supergroup').data(marks, function(d, i) {
+ return i + '-' + d.per.join('-');
+ });
- //set lower limit of linear domain to 0 when other axis is ordinal and mark type is set to 'bar', provided no values are negative
- if (mark.type === 'bar') {
- if (
- config.x.behavior !== 'flex' &&
- config.x.type === 'linear' &&
- config.y.type === 'ordinal' &&
- raw_dom_x[0] >= 0
- )
- x_dom[0] = 0;
+ line_supergroups.enter().append('g').attr('class', function(d) {
+ return 'supergroup line-supergroup ' + d.id;
+ });
- if (
- config.y.behavior !== 'flex' &&
- config.x.type === 'ordinal' &&
- config.y.type === 'linear' &&
- raw_dom_y[0] >= 0
- )
- y_dom[0] = 0;
- }
+ line_supergroups.exit().remove();
- //update domains with those specified in the config
- if (config.x.domain && (config.x.domain[0] || config.x.domain[0] === 0)) {
- x_dom[0] = config.x.domain[0];
- }
- if (config.x.domain && (config.x.domain[1] || config.x.domain[1] === 0)) {
- x_dom[1] = config.x.domain[1];
- }
- if (config.y.domain && (config.y.domain[0] || config.y.domain[0] === 0)) {
- y_dom[0] = config.y.domain[0];
- }
- if (config.y.domain && (config.y.domain[1] || config.y.domain[1] === 0)) {
- y_dom[1] = config.y.domain[1];
- }
+ var line_grps = line_supergroups.selectAll('.line').data(
+ function(d) {
+ return d.data;
+ },
+ function(d) {
+ return d.key;
+ }
+ );
+ line_grps.exit().remove();
+ var nu_line_grps = line_grps.enter().append('g').attr('class', function(d) {
+ return d.key + ' line';
+ });
+ nu_line_grps.append('path');
+ nu_line_grps.append('title');
- if (config.x.type === 'ordinal' && !config.x.order) {
- config.x.order = current_nested.totalOrder;
- }
- if (config.y.type === 'ordinal' && !config.y.order) {
- config.y.order = current_nested.totalOrder;
- }
+ var linePaths = line_grps
+ .select('path')
+ .attr('class', 'wc-data-mark')
+ .datum(function(d) {
+ return d.values;
+ })
+ .attr('stroke', function(d) {
+ return _this.colorScale(d[0].values.raw[0][config.color_by]);
+ })
+ .attr(
+ 'stroke-width',
+ config.stroke_width ? config.stroke_width : config.flex_stroke_width
+ )
+ .attr('stroke-linecap', 'round')
+ .attr('fill', 'none');
+ var linePathsTrans = config.transitions ? linePaths.transition() : linePaths;
+ linePathsTrans.attr('d', line);
- this.current_data = current_nested.nested;
+ line_grps.each(function(d) {
+ var mark = d3.select(this.parentNode).datum();
+ d.tooltip = mark.tooltip;
+ d3.select(this).select('path').attr(mark.attributes);
+ });
- this.events.onDatatransform.call(this);
+ line_grps.select('title').text(function(d) {
+ var tt = d.tooltip || '';
+ var xformat = config.x.summary === 'percent'
+ ? d3.format('0%')
+ : d3.format(config.x.format);
+ var yformat = config.y.summary === 'percent'
+ ? d3.format('0%')
+ : d3.format(config.y.format);
+ return tt
+ .replace(/\$x/g, xformat(d.values.x))
+ .replace(/\$y/g, yformat(d.values.y))
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values[0].values.raw[0][orig];
+ });
+ });
- return { config: mark, data: current_nested.nested, x_dom: x_dom, y_dom: y_dom };
+ //Link to the d3.selection from the data
+ line_supergroups.each(function(d) {
+ d.supergroup = d3.select(this);
+ d.groups = d.supergroup.selectAll('g.line');
+ d.paths = d.groups.select('path');
+ });
+ return line_grps;
}
- function setColorScale() {
- var config = this.config;
- var data = config.legend.behavior === 'flex' ? this.filtered_data : this.raw_data;
- var colordom = Array.isArray(config.color_dom) && config.color_dom.length
- ? config.color_dom.slice()
- : d3
- .set(
- data.map(function(m) {
- return m[config.color_by];
- })
- )
- .values()
- .filter(function(f) {
- return f && f !== 'undefined';
- });
-
- if (config.legend.order)
- colordom.sort(function(a, b) {
- return d3.ascending(config.legend.order.indexOf(a), config.legend.order.indexOf(b));
- });
- else colordom.sort(naturalSorter);
-
- this.colorScale = d3.scale.ordinal().domain(colordom).range(config.colors);
- }
+ function drawPoints(marks) {
+ var _this = this;
- function xScaleAxis(max_range, domain, type) {
- if (max_range === undefined) {
- max_range = this.plot_width;
- }
- if (domain === undefined) {
- domain = this.x_dom;
- }
- if (type === undefined) {
- type = this.config.x.type;
- }
var config = this.config;
- var x = void 0;
- if (type === 'log') {
- x = d3.scale.log();
- } else if (type === 'ordinal') {
- x = d3.scale.ordinal();
- } else if (type === 'time') {
- x = d3.time.scale();
- } else {
- x = d3.scale.linear();
- }
-
- x.domain(domain);
-
- if (type === 'ordinal') {
- x.rangeBands([0, +max_range], config.padding, config.outer_pad);
- } else {
- x.range([0, +max_range]).clamp(Boolean(config.x.clamp));
- }
+ var point_supergroups = this.svg.selectAll('.point-supergroup').data(marks, function(d, i) {
+ return i + '-' + d.per.join('-');
+ });
- var xFormat = config.x.format
- ? config.x.format
- : config.marks
- .map(function(m) {
- return m.summarizeX === 'percent';
- })
- .indexOf(true) > -1
- ? '0%'
- : type === 'time' ? '%x' : '.0f';
- var tick_count = Math.max(2, Math.min(max_range / 80, 8));
- var xAxis = d3.svg
- .axis()
- .scale(x)
- .orient(config.x.location)
- .ticks(tick_count)
- .tickFormat(
- type === 'ordinal'
- ? null
- : type === 'time' ? d3.time.format(xFormat) : d3.format(xFormat)
- )
- .tickValues(config.x.ticks ? config.x.ticks : null)
- .innerTickSize(6)
- .outerTickSize(3);
+ point_supergroups.enter().append('g').attr('class', function(d) {
+ return 'supergroup point-supergroup ' + d.id;
+ });
- this.svg.select('g.x.axis').attr('class', 'x axis ' + type);
- this.x = x;
- this.xAxis = xAxis;
- }
+ point_supergroups.exit().remove();
- function yScaleAxis(max_range, domain, type) {
- if (max_range === undefined) {
- max_range = this.plot_height;
- }
- if (domain === undefined) {
- domain = this.y_dom;
- }
- if (type === undefined) {
- type = this.config.y.type;
- }
- var config = this.config;
- var y = void 0;
- if (type === 'log') {
- y = d3.scale.log();
- } else if (type === 'ordinal') {
- y = d3.scale.ordinal();
- } else if (type === 'time') {
- y = d3.time.scale();
- } else {
- y = d3.scale.linear();
- }
+ var points = point_supergroups.selectAll('.point').data(
+ function(d) {
+ return d.data;
+ },
+ function(d) {
+ return d.key;
+ }
+ );
+ var oldPoints = points.exit();
- y.domain(domain);
+ var oldPointsTrans = config.transitions
+ ? oldPoints.selectAll('circle').transition()
+ : oldPoints.selectAll('circle');
+ oldPointsTrans.attr('r', 0);
- if (type === 'ordinal') {
- y.rangeBands([+max_range, 0], config.padding, config.outer_pad);
- } else {
- y.range([+max_range, 0]).clamp(Boolean(config.y_clamp));
- }
+ var oldPointGroupTrans = config.transitions ? oldPoints.transition() : oldPoints;
+ oldPointGroupTrans.remove();
- var yFormat = config.y.format
- ? config.y.format
- : config.marks
- .map(function(m) {
- return m.summarizeY === 'percent';
- })
- .indexOf(true) > -1
- ? '0%'
- : '.0f';
- var tick_count = Math.max(2, Math.min(max_range / 80, 8));
- var yAxis = d3.svg
- .axis()
- .scale(y)
- .orient('left')
- .ticks(tick_count)
- .tickFormat(
- type === 'ordinal'
- ? null
- : type === 'time' ? d3.time.format(yFormat) : d3.format(yFormat)
+ var nupoints = points.enter().append('g').attr('class', function(d) {
+ return d.key + ' point';
+ });
+ nupoints.append('circle').attr('class', 'wc-data-mark').attr('r', 0);
+ nupoints.append('title');
+ //static attributes
+ points
+ .select('circle')
+ .attr(
+ 'fill-opacity',
+ config.fill_opacity || config.fill_opacity === 0 ? config.fill_opacity : 0.6
)
- .tickValues(config.y.ticks ? config.y.ticks : null)
- .innerTickSize(6)
- .outerTickSize(3);
+ .attr('fill', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ })
+ .attr('stroke', function(d) {
+ return _this.colorScale(d.values.raw[0][config.color_by]);
+ });
+ //attach mark info
+ points.each(function(d) {
+ var mark = d3.select(this.parentNode).datum();
+ d.mark = mark;
+ d3.select(this).select('circle').attr(mark.attributes);
+ });
+ //animated attributes
+ var pointsTrans = config.transitions
+ ? points.select('circle').transition()
+ : points.select('circle');
+ pointsTrans
+ .attr('r', function(d) {
+ return d.mark.radius || config.flex_point_size;
+ })
+ .attr('cx', function(d) {
+ var x_pos = _this.x(d.values.x) || 0;
+ return config.x.type === 'ordinal' ? x_pos + _this.x.rangeBand() / 2 : x_pos;
+ })
+ .attr('cy', function(d) {
+ var y_pos = _this.y(d.values.y) || 0;
+ return config.y.type === 'ordinal' ? y_pos + _this.y.rangeBand() / 2 : y_pos;
+ });
+
+ points.select('title').text(function(d) {
+ var tt = d.mark.tooltip || '';
+ var xformat = config.x.summary === 'percent'
+ ? d3.format('0%')
+ : config.x.type === 'time'
+ ? d3.time.format(config.x.format)
+ : d3.format(config.x.format);
+ var yformat = config.y.summary === 'percent'
+ ? d3.format('0%')
+ : config.y.type === 'time'
+ ? d3.time.format(config.y.format)
+ : d3.format(config.y.format);
+ return tt
+ .replace(
+ /\$x/g,
+ config.x.type === 'time' ? xformat(new Date(d.values.x)) : xformat(d.values.x)
+ )
+ .replace(
+ /\$y/g,
+ config.y.type === 'time' ? yformat(new Date(d.values.y)) : yformat(d.values.y)
+ )
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
+ });
+ });
- this.svg.select('g.y.axis').attr('class', 'y axis ' + type);
+ //Link to the d3.selection from the data
+ point_supergroups.each(function(d) {
+ d.supergroup = d3.select(this);
+ d.groups = d.supergroup.selectAll('g.point');
+ d.circles = d.groups.select('circle');
+ });
- this.y = y;
- this.yAxis = yAxis;
+ return points;
}
- function resize() {
- var config = this.config;
-
- var aspect2 = 1 / config.aspect;
- var div_width = parseInt(this.wrap.style('width'));
- var max_width = config.max_width ? config.max_width : div_width;
- var preWidth = !config.resizable
- ? config.width
- : !max_width || div_width < max_width ? div_width : this.raw_width;
+ function drawText(marks) {
+ var _this = this;
- this.textSize(preWidth);
+ var config = this.config;
- this.margin = this.setMargins();
+ var textSupergroups = this.svg.selectAll('.text-supergroup').data(marks, function(d, i) {
+ return i + '-' + d.per.join('-');
+ });
- var svg_width = config.x.type === 'ordinal' && +config.x.range_band
- ? this.raw_width + this.margin.left + this.margin.right
- : !config.resizable
- ? this.raw_width
- : !config.max_width || div_width < config.max_width ? div_width : this.raw_width;
- this.plot_width = svg_width - this.margin.left - this.margin.right;
- var svg_height = config.y.type === 'ordinal' && +config.y.range_band
- ? this.raw_height + this.margin.top + this.margin.bottom
- : !config.resizable && config.height
- ? config.height
- : !config.resizable ? svg_width * aspect2 : this.plot_width * aspect2;
- this.plot_height = svg_height - this.margin.top - this.margin.bottom;
+ textSupergroups.enter().append('g').attr('class', function(d) {
+ return 'supergroup text-supergroup ' + d.id;
+ });
- d3
- .select(this.svg.node().parentNode)
- .attr('width', svg_width)
- .attr('height', svg_height)
- .select('g')
- .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
+ textSupergroups.exit().remove();
- this.svg
- .select('.overlay')
- .attr('width', this.plot_width)
- .attr('height', this.plot_height)
- .classed('zoomable', config.zoomable);
+ var texts = textSupergroups.selectAll('.text').data(
+ function(d) {
+ return d.data;
+ },
+ function(d) {
+ return d.key;
+ }
+ );
+ var oldTexts = texts.exit();
- this.svg
- .select('.plotting-area')
- .attr('width', this.plot_width)
- .attr('height', this.plot_height + 1)
- .attr('transform', 'translate(0, -1)');
+ // don't need to transition position of outgoing text
+ // const oldTextsTrans = config.transitions ? oldTexts.selectAll('text').transition() : oldTexts.selectAll('text');
- this.xScaleAxis();
- this.yScaleAxis();
+ var oldTextGroupTrans = config.transitions ? oldTexts.transition() : oldTexts;
+ oldTextGroupTrans.remove();
- var g_x_axis = this.svg.select('.x.axis');
- var g_y_axis = this.svg.select('.y.axis');
- var x_axis_label = g_x_axis.select('.axis-title');
- var y_axis_label = g_y_axis.select('.axis-title');
+ var nutexts = texts.enter().append('g').attr('class', function(d) {
+ return d.key + ' text';
+ });
+ nutexts.append('text').attr('class', 'wc-data-mark');
+ // don't need to set initial location for incoming text
- if (config.x_location !== 'top') {
- g_x_axis.attr('transform', 'translate(0,' + this.plot_height + ')');
+ // attach mark info
+ function attachMarks(d) {
+ d.mark = d3.select(this.parentNode).datum();
+ d3.select(this).select('text').attr(d.mark.attributes);
}
- var gXAxisTrans = config.transitions ? g_x_axis.transition() : g_x_axis;
- gXAxisTrans.call(this.xAxis);
- var gYAxisTrans = config.transitions ? g_y_axis.transition() : g_y_axis;
- gYAxisTrans.call(this.yAxis);
-
- x_axis_label.attr(
- 'transform',
- 'translate(' + this.plot_width / 2 + ',' + (this.margin.bottom - 2) + ')'
- );
- y_axis_label.attr('x', -1 * this.plot_height / 2).attr('y', -1 * this.margin.left);
+ texts.each(attachMarks);
- this.svg
- .selectAll('.axis .domain')
- .attr({
- fill: 'none',
- stroke: '#ccc',
- 'stroke-width': 1,
- 'shape-rendering': 'crispEdges'
+ // parse text like tooltips
+ texts.select('text').text(function(d) {
+ var tt = d.mark.text || '';
+ var xformat = config.x.summary === 'percent'
+ ? d3.format('0%')
+ : config.x.type === 'time'
+ ? d3.time.format(config.x.format)
+ : d3.format(config.x.format);
+ var yformat = config.y.summary === 'percent'
+ ? d3.format('0%')
+ : config.y.type === 'time'
+ ? d3.time.format(config.y.format)
+ : d3.format(config.y.format);
+ return tt
+ .replace(
+ /\$x/g,
+ config.x.type === 'time' ? xformat(new Date(d.values.x)) : xformat(d.values.x)
+ )
+ .replace(
+ /\$y/g,
+ config.y.type === 'time' ? yformat(new Date(d.values.y)) : yformat(d.values.y)
+ )
+ .replace(/\[(.+?)\]/g, function(str, orig) {
+ return d.values.raw[0][orig];
+ });
+ });
+ // animated attributes
+ var textsTrans = config.transitions
+ ? texts.select('text').transition()
+ : texts.select('text');
+ textsTrans
+ .attr('x', function(d) {
+ var xPos = _this.x(d.values.x) || 0;
+ return config.x.type === 'ordinal' ? xPos + _this.x.rangeBand() / 2 : xPos;
+ })
+ .attr('y', function(d) {
+ var yPos = _this.y(d.values.y) || 0;
+ return config.y.type === 'ordinal' ? yPos + _this.y.rangeBand() / 2 : yPos;
});
- this.svg
- .selectAll('.axis .tick line')
- .attr({ stroke: '#eee', 'stroke-width': 1, 'shape-rendering': 'crispEdges' });
+ //add a reference to the selection from it's data
+ textSupergroups.each(function(d) {
+ d.supergroup = d3.select(this);
+ d.groups = d.supergroup.selectAll('g.text');
+ d.texts = d.groups.select('text');
+ });
+ return texts;
+ }
- this.drawGridlines();
+ function init(data) {
+ var _this = this;
- //update legend - margins need to be set first
- this.makeLegend();
+ var test = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- //update the chart's specific marks
- this.updateDataMarks();
+ if (d3.select(this.div).select('.loader').empty()) {
+ d3
+ .select(this.div)
+ .insert('div', ':first-child')
+ .attr('class', 'loader')
+ .selectAll('.blockG')
+ .data(d3.range(8))
+ .enter()
+ .append('div')
+ .attr('class', function(d) {
+ return 'blockG rotate' + (d + 1);
+ });
+ }
- //call .on("resize") function, if any
- this.events.onResize.call(this);
- }
+ this.wrap.attr('class', 'wc-chart');
- function textSize(width) {
- var font_size = '14px';
- var point_size = 4;
- var stroke_width = 2;
+ this.setDefaults();
- if (!this.config.scale_text) {
- font_size = this.config.font_size;
- point_size = this.config.point_size || 4;
- stroke_width = this.config.stroke_width || 2;
- } else if (width >= 600) {
- font_size = '14px';
- point_size = 4;
- stroke_width = 2;
- } else if (width > 450 && width < 600) {
- font_size = '12px';
- point_size = 3;
- stroke_width = 2;
- } else if (width > 300 && width < 450) {
- font_size = '10px';
- point_size = 2;
- stroke_width = 2;
- } else if (width <= 300) {
- font_size = '10px';
- point_size = 2;
- stroke_width = 1;
- }
+ this.raw_data = data;
+ this.initial_data = data;
- this.wrap.style('font-size', font_size);
- this.config.flex_point_size = point_size;
- this.config.flex_stroke_width = stroke_width;
- }
+ var startup = function startup(data) {
+ //connect this chart and its controls, if any
+ if (_this.controls) {
+ _this.controls.targets.push(_this);
+ if (!_this.controls.ready) {
+ _this.controls.init(_this.raw_data);
+ } else {
+ _this.controls.layout();
+ }
+ }
- function setMargins() {
- var _this = this;
+ //make sure container is visible (has height and width) before trying to initialize
+ var visible = d3.select(_this.div).property('offsetWidth') > 0 || test;
+ if (!visible) {
+ console.warn(
+ 'The chart cannot be initialized inside an element with 0 width. The chart will be initialized as soon as the container element is given a width > 0.'
+ );
+ var onVisible = setInterval(function(i) {
+ var visible_now = d3.select(_this.div).property('offsetWidth') > 0;
+ if (visible_now) {
+ _this.layout();
+ _this.draw();
+ clearInterval(onVisible);
+ }
+ }, 500);
+ } else {
+ _this.layout();
+ _this.draw();
+ }
+ };
- var y_ticks = this.yAxis.tickFormat()
- ? this.y.domain().map(function(m) {
- return _this.yAxis.tickFormat()(m);
- })
- : this.y.domain();
+ this.events.onInit.call(this);
+ if (this.raw_data.length) {
+ this.checkRequired(this.raw_data);
+ }
+ startup(data);
- var max_y_text_length = d3.max(
- y_ticks.map(function(m) {
- return String(m).length;
+ return this;
+ }
+
+ function layout() {
+ this.svg = this.wrap
+ .append('svg')
+ .datum(function() {
+ return null;
+ }) // prevent data inheritance
+ .attr({
+ class: 'wc-svg',
+ xmlns: 'http://www.w3.org/2000/svg',
+ version: '1.1',
+ xlink: 'http://www.w3.org/1999/xlink'
})
- );
- if (this.config.y_format && this.config.y_format.indexOf('%') > -1) {
- max_y_text_length += 1;
- }
- max_y_text_length = Math.max(2, max_y_text_length);
- var x_label_on = this.config.x.label ? 1.5 : 0;
- var y_label_on = this.config.y.label ? 1.5 : 0.25;
- var font_size = parseInt(this.wrap.style('font-size'));
- var x_second = this.config.x2_interval ? 1 : 0;
- var y_margin = max_y_text_length * font_size * 0.5 + font_size * y_label_on * 1.5 || 8;
- var x_margin =
- font_size + font_size / 1.5 + font_size * x_label_on + font_size * x_second || 8;
+ .append('g')
+ .style('display', 'inline-block');
- y_margin += 6;
- x_margin += 3;
+ var defs = this.svg.append('defs');
+ defs
+ .append('pattern')
+ .attr({
+ id: 'diagonal-stripes',
+ x: 0,
+ y: 0,
+ width: 3,
+ height: 8,
+ patternUnits: 'userSpaceOnUse',
+ patternTransform: 'rotate(30)'
+ })
+ .append('rect')
+ .attr({ x: '0', y: '0', width: '2', height: '8', style: 'stroke:none; fill:black' });
- return {
- top: this.config.margin && this.config.margin.top ? this.config.margin.top : 8,
- right: this.config.margin && this.config.margin.right ? this.config.margin.right : 16,
- bottom: this.config.margin && this.config.margin.bottom
- ? this.config.margin.bottom
- : x_margin,
- left: this.config.margin && this.config.margin.left ? this.config.margin.left : y_margin
- };
- }
+ defs.append('clipPath').attr('id', this.id).append('rect').attr('class', 'plotting-area');
- function drawGridLines() {
- this.wrap.classed('gridlines', this.config.gridlines);
- if (this.config.gridlines) {
- this.svg.select('.y.axis').selectAll('.tick line').attr('x1', 0);
- this.svg.select('.x.axis').selectAll('.tick line').attr('y1', 0);
- if (this.config.gridlines === 'y' || this.config.gridlines === 'xy')
- this.svg.select('.y.axis').selectAll('.tick line').attr('x1', this.plot_width);
- if (this.config.gridlines === 'x' || this.config.gridlines === 'xy')
- this.svg.select('.x.axis').selectAll('.tick line').attr('y1', -this.plot_height);
- } else {
- this.svg.select('.y.axis').selectAll('.tick line').attr('x1', 0);
- this.svg.select('.x.axis').selectAll('.tick line').attr('y1', 0);
- }
+ //y axis
+ this.svg
+ .append('g')
+ .attr('class', 'y axis')
+ .append('text')
+ .attr('class', 'axis-title')
+ .attr('transform', 'rotate(-90)')
+ .attr('dy', '.75em')
+ .attr('text-anchor', 'middle');
+ //x axis
+ this.svg
+ .append('g')
+ .attr('class', 'x axis')
+ .append('text')
+ .attr('class', 'axis-title')
+ .attr('dy', '-.35em')
+ .attr('text-anchor', 'middle');
+ //overlay
+ this.svg
+ .append('rect')
+ .attr('class', 'overlay')
+ .attr('opacity', 0)
+ .attr('fill', 'none')
+ .style('pointer-events', 'all');
+ //add legend
+ var legend = this.wrap.append('ul').datum(function() {
+ return null;
+ }); // prevent data inheritance
+ legend
+ .attr('class', 'legend')
+ .style('vertical-align', 'top')
+ .append('span')
+ .attr('class', 'legend-title');
+
+ d3.select(this.div).select('.loader').remove();
+
+ this.events.onLayout.call(this);
}
function makeLegend() {
@@ -1564,27 +1418,11 @@
var legendOriginal = this.legend || this.wrap.select('.legend');
var legend = legendOriginal;
- if (!this.parent) {
- //singular chart
- if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
- this.wrap.node().insertBefore(legendOriginal.node(), this.svg.node().parentNode);
- } else {
- this.wrap.node().appendChild(legendOriginal.node());
- }
+ if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
+ this.wrap.node().insertBefore(legendOriginal.node(), this.svg.node().parentNode);
} else {
- //multiples - keep legend outside of individual charts' wraps
- if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
- this.parent.wrap
- .node()
- .insertBefore(
- legendOriginal.node(),
- this.parent.wrap.select('.wc-chart').node()
- );
- } else {
- this.parent.wrap.node().appendChild(legendOriginal.node());
- }
+ this.wrap.node().appendChild(legendOriginal.node());
}
-
legend.style('padding', 0);
var legend_data =
@@ -1650,7 +1488,7 @@
if (e.mark === 'circle') {
svg$$1
.append('circle')
- .attr({ cx: '.5em', cy: '.5em', r: '.45em', class: 'legend-mark' });
+ .attr({ cx: '.5em', cy: '.45em', r: '.45em', class: 'legend-mark' });
} else if (e.mark === 'line') {
svg$$1.append('line').attr({
x1: 0,
@@ -1692,9 +1530,8 @@
});
if (scale$$1.domain().length > 0) {
- var legendDisplay = (this.config.legend.location === 'bottom' ||
- this.config.legend.location === 'top') &&
- !this.parent
+ var legendDisplay = this.config.legend.location === 'bottom' ||
+ this.config.legend.location === 'top'
? 'block'
: 'inline-block';
legend.style('display', legendDisplay);
@@ -1705,925 +1542,968 @@
this.legend = legend;
}
- function updateDataMarks() {
- this.drawBars(
- this.marks.filter(function(f) {
- return f.type === 'bar';
- })
- );
- this.drawLines(
- this.marks.filter(function(f) {
- return f.type === 'line';
- })
- );
- this.drawPoints(
- this.marks.filter(function(f) {
- return f.type === 'circle';
- })
- );
- this.drawText(
- this.marks.filter(function(f) {
- return f.type === 'text';
- })
- );
+ function resize() {
+ var config = this.config;
- this.marks.supergroups = this.svg.selectAll('g.supergroup');
- }
+ var aspect2 = 1 / config.aspect;
+ var div_width = parseInt(this.wrap.style('width'));
+ var max_width = config.max_width ? config.max_width : div_width;
+ var preWidth = !config.resizable
+ ? config.width
+ : !max_width || div_width < max_width ? div_width : this.raw_width;
- function drawArea(area_drawer, area_data, datum_accessor) {
- var class_match = arguments.length > 3 && arguments[3] !== undefined
- ? arguments[3]
- : 'chart-area';
+ this.textSize(preWidth);
- var _this = this;
+ this.margin = this.setMargins();
- var bind_accessor = arguments[4];
- var attr_accessor = arguments.length > 5 && arguments[5] !== undefined
- ? arguments[5]
- : function(d) {
- return d;
- };
+ var svg_width = config.x.type === 'ordinal' && +config.range_band
+ ? this.raw_width + this.margin.left + this.margin.right
+ : !config.resizable
+ ? this.raw_width
+ : !config.max_width || div_width < config.max_width ? div_width : this.raw_width;
+ this.plot_width = svg_width - this.margin.left - this.margin.right;
+ var svg_height = config.y.type === 'ordinal' && +config.range_band
+ ? this.raw_height + this.margin.top + this.margin.bottom
+ : !config.resizable && config.height
+ ? config.height
+ : !config.resizable ? svg_width * aspect2 : this.plot_width * aspect2;
+ this.plot_height = svg_height - this.margin.top - this.margin.bottom;
- var area_grps = this.svg.selectAll('.' + class_match).data(area_data, bind_accessor);
- area_grps.exit().remove();
- area_grps
- .enter()
- .append('g')
- .attr('class', function(d) {
- return class_match + ' ' + d.key;
- })
- .append('path');
+ d3
+ .select(this.svg.node().parentNode)
+ .attr('width', svg_width)
+ .attr('height', svg_height)
+ .select('g')
+ .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
- var areaPaths = area_grps
- .select('path')
- .datum(datum_accessor)
- .attr('fill', function(d) {
- var d_attr = attr_accessor(d);
- return d_attr ? _this.colorScale(d_attr[_this.config.color_by]) : null;
- })
- .attr(
- 'fill-opacity',
- this.config.fill_opacity || this.config.fill_opacity === 0
- ? this.config.fill_opacity
- : 0.3
- );
+ this.svg
+ .select('.overlay')
+ .attr('width', this.plot_width)
+ .attr('height', this.plot_height)
+ .classed('zoomable', config.zoomable);
- //don't transition if config says not to
- var areaPathTransitions = this.config.transitions ? areaPaths.transition() : areaPaths;
+ this.svg
+ .select('.plotting-area')
+ .attr('width', this.plot_width)
+ .attr('height', this.plot_height + 1)
+ .attr('transform', 'translate(0, -1)');
+
+ this.xScaleAxis();
+ this.yScaleAxis();
+
+ var g_x_axis = this.svg.select('.x.axis');
+ var g_y_axis = this.svg.select('.y.axis');
+ var x_axis_label = g_x_axis.select('.axis-title');
+ var y_axis_label = g_y_axis.select('.axis-title');
+
+ if (config.x_location !== 'top') {
+ g_x_axis.attr('transform', 'translate(0,' + this.plot_height + ')');
+ }
+ var gXAxisTrans = config.transitions ? g_x_axis.transition() : g_x_axis;
+ gXAxisTrans.call(this.xAxis);
+ var gYAxisTrans = config.transitions ? g_y_axis.transition() : g_y_axis;
+ gYAxisTrans.call(this.yAxis);
+
+ x_axis_label.attr(
+ 'transform',
+ 'translate(' + this.plot_width / 2 + ',' + (this.margin.bottom - 2) + ')'
+ );
+ y_axis_label.attr('x', -1 * this.plot_height / 2).attr('y', -1 * this.margin.left);
+
+ this.svg
+ .selectAll('.axis .domain')
+ .attr({
+ fill: 'none',
+ stroke: '#ccc',
+ 'stroke-width': 1,
+ 'shape-rendering': 'crispEdges'
+ });
+ this.svg
+ .selectAll('.axis .tick line')
+ .attr({ stroke: '#eee', 'stroke-width': 1, 'shape-rendering': 'crispEdges' });
+
+ this.drawGridlines();
+ //update legend - margins need to be set first
+ this.makeLegend();
+
+ //update the chart's specific marks
+ this.updateDataMarks();
+
+ //call .on("resize") function, if any
+ this.events.onResize.call(this);
+ }
+
+ function setColorScale() {
+ var config = this.config;
+ var data = config.legend.behavior === 'flex' ? this.filtered_data : this.raw_data;
+ var colordom = Array.isArray(config.color_dom) && config.color_dom.length
+ ? config.color_dom.slice()
+ : d3
+ .set(
+ data.map(function(m) {
+ return m[config.color_by];
+ })
+ )
+ .values()
+ .filter(function(f) {
+ return f && f !== 'undefined';
+ });
- areaPathTransitions.attr('d', area_drawer);
+ if (config.legend.order)
+ colordom.sort(function(a, b) {
+ return d3.ascending(config.legend.order.indexOf(a), config.legend.order.indexOf(b));
+ });
+ else colordom.sort(naturalSorter);
- return area_grps;
+ this.colorScale = d3.scale.ordinal().domain(colordom).range(config.colors);
}
- function drawBars(marks) {
- var _this = this;
+ function setDefaults() {
+ this.config.x = this.config.x || {};
+ this.config.y = this.config.y || {};
- var rawData = this.raw_data;
- var config = this.config;
+ this.config.x.label = this.config.x.label !== undefined
+ ? this.config.x.label
+ : this.config.x.column;
+ this.config.y.label = this.config.y.label !== undefined
+ ? this.config.y.label
+ : this.config.y.column;
- var bar_supergroups = this.svg.selectAll('.bar-supergroup').data(marks, function(d, i) {
- return i + '-' + d.per.join('-');
- });
+ this.config.x.sort = this.config.x.sort || 'alphabetical-ascending';
+ this.config.y.sort = this.config.y.sort || 'alphabetical-descending';
- bar_supergroups.enter().append('g').attr('class', function(d) {
- return 'supergroup bar-supergroup ' + d.id;
+ this.config.x.type = this.config.x.type || 'linear';
+ this.config.y.type = this.config.y.type || 'linear';
+
+ this.config.margin = this.config.margin || {};
+ this.config.legend = this.config.legend || {};
+ this.config.legend.label = this.config.legend.label !== undefined
+ ? this.config.legend.label
+ : this.config.color_by;
+ this.config.legend.location = this.config.legend.location !== undefined
+ ? this.config.legend.location
+ : 'bottom';
+ this.config.marks = this.config.marks && this.config.marks.length
+ ? this.config.marks
+ : [{}];
+ this.config.marks.forEach(function(m, i) {
+ m.id = m.id ? m.id : 'mark' + (i + 1);
});
- bar_supergroups.exit().remove();
+ this.config.date_format = this.config.date_format || '%x';
- var bar_groups = bar_supergroups.selectAll('.bar-group').data(
- function(d) {
- return d.data;
- },
- function(d) {
- return d.key;
- }
- );
- var old_bar_groups = bar_groups.exit();
+ this.config.padding = this.config.padding !== undefined ? this.config.padding : 0.3;
+ this.config.outer_pad = this.config.outer_pad !== undefined ? this.config.outer_pad : 0.1;
- var nu_bar_groups = void 0;
- var bars = void 0;
+ this.config.resizable = this.config.resizable !== undefined ? this.config.resizable : true;
- var oldBarsTrans = config.transitions
- ? old_bar_groups.selectAll('.bar').transition()
- : old_bar_groups.selectAll('.bar');
- var oldBarGroupsTrans = config.transitions ? old_bar_groups.transition() : old_bar_groups;
+ this.config.aspect = this.config.aspect || 1.33;
- if (config.x.type === 'ordinal') {
- oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
+ this.config.colors = this.config.colors || [
+ 'rgb(102,194,165)',
+ 'rgb(252,141,98)',
+ 'rgb(141,160,203)',
+ 'rgb(231,138,195)',
+ 'rgb(166,216,84)',
+ 'rgb(255,217,47)',
+ 'rgb(229,196,148)',
+ 'rgb(179,179,179)'
+ ];
- oldBarGroupsTrans.remove();
+ this.config.scale_text = this.config.scale_text === undefined
+ ? true
+ : this.config.scale_text;
+ this.config.transitions = this.config.transitions === undefined
+ ? true
+ : this.config.transitions;
+ }
- nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
- return 'bar-group ' + d.key;
- });
- nu_bar_groups.append('title');
+ function setMargins() {
+ var _this = this;
- bars = bar_groups.selectAll('rect').data(
- function(d) {
- return d.values instanceof Array
- ? d.values.sort(function(a, b) {
- return (
- _this.colorScale.domain().indexOf(b.key) -
- _this.colorScale.domain().indexOf(a.key)
- );
- })
- : [d];
- },
- function(d) {
- return d.key;
- }
- );
+ var y_ticks = this.yAxis.tickFormat()
+ ? this.y.domain().map(function(m) {
+ return _this.yAxis.tickFormat()(m);
+ })
+ : this.y.domain();
- var exitBars = config.transitions ? bars.exit().transition() : bars.exit();
- exitBars.attr('y', this.y(0)).attr('height', 0).remove();
- bars
- .enter()
- .append('rect')
- .attr('class', function(d) {
- return 'wc-data-mark bar ' + d.key;
- })
- .style('clip-path', 'url(#' + this.id + ')')
- .attr('y', this.y(0))
- .attr('height', 0)
- .append('title');
+ var max_y_text_length = d3.max(
+ y_ticks.map(function(m) {
+ return String(m).length;
+ })
+ );
+ if (this.config.y_format && this.config.y_format.indexOf('%') > -1) {
+ max_y_text_length += 1;
+ }
+ max_y_text_length = Math.max(2, max_y_text_length);
+ var x_label_on = this.config.x.label ? 1.5 : 0;
+ var y_label_on = this.config.y.label ? 1.5 : 0.25;
+ var font_size = parseInt(this.wrap.style('font-size'));
+ var x_second = this.config.x2_interval ? 1 : 0;
+ var y_margin = max_y_text_length * font_size * 0.5 + font_size * y_label_on * 1.5 || 8;
+ var x_margin =
+ font_size + font_size / 1.5 + font_size * x_label_on + font_size * x_second || 8;
- bars
- .attr('shape-rendering', 'crispEdges')
- .attr('stroke', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- })
- .attr('fill', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- });
+ y_margin += 6;
+ x_margin += 3;
- bars.each(function(d) {
- var mark = d3.select(this.parentNode.parentNode).datum();
- d.tooltip = mark.tooltip;
- d.arrange = mark.split && mark.arrange
- ? mark.arrange
- : mark.split ? 'grouped' : null;
- d.subcats = config.legend.order
- ? config.legend.order.slice().reverse()
- : mark.values && mark.values[mark.split]
- ? mark.values[mark.split]
- : d3
- .set(
- rawData.map(function(m) {
- return m[mark.split];
- })
- )
- .values();
- d3.select(this).attr(mark.attributes);
- });
+ return {
+ top: this.config.margin && this.config.margin.top ? this.config.margin.top : 8,
+ right: this.config.margin && this.config.margin.right ? this.config.margin.right : 16,
+ bottom: this.config.margin && this.config.margin.bottom
+ ? this.config.margin.bottom
+ : x_margin,
+ left: this.config.margin && this.config.margin.left ? this.config.margin.left : y_margin
+ };
+ }
- var xformat = config.marks
- .map(function(m) {
- return m.summarizeX === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.x.format);
- var yformat = config.marks
- .map(function(m) {
- return m.summarizeY === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.y.format);
- bars.select('title').text(function(d) {
- var tt = d.tooltip || '';
- return tt
- .replace(/\$x/g, xformat(d.values.x))
- .replace(/\$y/g, yformat(d.values.y))
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
- });
- });
+ function textSize(width) {
+ var font_size = '14px';
+ var point_size = 4;
+ var stroke_width = 2;
- var barsTrans = config.transitions ? bars.transition() : bars;
- barsTrans
- .attr('x', function(d) {
- var position = void 0;
- if (!d.arrange || d.arrange === 'stacked') {
- return _this.x(d.values.x);
- } else if (d.arrange === 'nested') {
- var _position = d.subcats.indexOf(d.key);
- var offset = _position
- ? _this.x.rangeBand() / (d.subcats.length * 0.75) / _position
- : _this.x.rangeBand();
- return _this.x(d.values.x) + (_this.x.rangeBand() - offset) / 2;
- } else {
- position = d.subcats.indexOf(d.key);
- return (
- _this.x(d.values.x) + _this.x.rangeBand() / d.subcats.length * position
- );
- }
- })
- .attr('y', function(d) {
- if (d.arrange !== 'stacked') {
- return _this.y(d.values.y);
- } else {
- return _this.y(d.values.start);
- }
- })
- .attr('width', function(d) {
- if (!d.arrange || d.arrange === 'stacked') {
- return _this.x.rangeBand();
- } else if (d.arrange === 'nested') {
- var position = d.subcats.indexOf(d.key);
- return position
- ? _this.x.rangeBand() / (d.subcats.length * 0.75) / position
- : _this.x.rangeBand();
- } else {
- return _this.x.rangeBand() / d.subcats.length;
- }
- })
- .attr('height', function(d) {
- return _this.y(0) - _this.y(d.values.y);
- });
- } else if (config.y.type === 'ordinal') {
- oldBarsTrans.attr('x', this.x(0)).attr('width', 0);
+ if (!this.config.scale_text) {
+ font_size = this.config.font_size;
+ point_size = this.config.point_size || 4;
+ stroke_width = this.config.stroke_width || 2;
+ } else if (width >= 600) {
+ font_size = '14px';
+ point_size = 4;
+ stroke_width = 2;
+ } else if (width > 450 && width < 600) {
+ font_size = '12px';
+ point_size = 3;
+ stroke_width = 2;
+ } else if (width > 300 && width < 450) {
+ font_size = '10px';
+ point_size = 2;
+ stroke_width = 2;
+ } else if (width <= 300) {
+ font_size = '10px';
+ point_size = 2;
+ stroke_width = 1;
+ }
- oldBarGroupsTrans.remove();
+ this.wrap.style('font-size', font_size);
+ this.config.flex_point_size = point_size;
+ this.config.flex_stroke_width = stroke_width;
+ }
- nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
- return 'bar-group ' + d.key;
- });
- nu_bar_groups.append('title');
+ var stats = {
+ mean: d3.mean,
+ min: d3.min,
+ max: d3.max,
+ median: d3.median,
+ sum: d3.sum
+ };
- bars = bar_groups.selectAll('rect').data(
- function(d) {
- return d.values instanceof Array
- ? d.values.sort(function(a, b) {
- return (
- _this.colorScale.domain().indexOf(b.key) -
- _this.colorScale.domain().indexOf(a.key)
- );
- })
- : [d];
- },
- function(d) {
- return d.key;
- }
- );
+ function summarize(vals) {
+ var operation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'mean';
- var _exitBars = config.transitions ? bars.exit().transition() : bars.exit();
- _exitBars.attr('x', this.x(0)).attr('width', 0).remove();
- bars
- .enter()
- .append('rect')
- .attr('class', function(d) {
- return 'wc-data-mark bar ' + d.key;
- })
- .style('clip-path', 'url(#' + this.id + ')')
- .attr('x', this.x(0))
- .attr('width', 0)
- .append('title');
+ var nvals = vals
+ .filter(function(f) {
+ return +f || +f === 0;
+ })
+ .map(function(m) {
+ return +m;
+ });
- bars
- .attr('shape-rendering', 'crispEdges')
- .attr('stroke', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- })
- .attr('fill', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- });
+ if (operation === 'cumulative') {
+ return null;
+ }
- bars.each(function(d) {
- var mark = d3.select(this.parentNode.parentNode).datum();
- d.arrange = mark.split && mark.arrange
- ? mark.arrange
- : mark.split ? 'grouped' : null;
- d.subcats = config.legend.order
- ? config.legend.order.slice().reverse()
- : mark.values && mark.values[mark.split]
- ? mark.values[mark.split]
- : d3
- .set(
- rawData.map(function(m) {
- return m[mark.split];
- })
- )
- .values();
- d.tooltip = mark.tooltip;
- d3.select(this).attr(mark.attributes);
- });
+ var mathed = operation === 'count'
+ ? vals.length
+ : operation === 'percent' ? vals.length : stats[operation](nvals);
- var _xformat = config.marks
- .map(function(m) {
- return m.summarizeX === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.x.format);
- var _yformat = config.marks
- .map(function(m) {
- return m.summarizeY === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.y.format);
- bars.select('title').text(function(d) {
- var tt = d.tooltip || '';
- return tt
- .replace(/\$x/g, _xformat(d.values.x))
- .replace(/\$y/g, _yformat(d.values.y))
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
- });
- });
+ return mathed;
+ }
- var _barsTrans = config.transitions ? bars.transition() : bars;
- _barsTrans
- .attr('x', function(d) {
- if (d.arrange === 'stacked' || !d.arrange) {
- return d.values.start !== undefined ? _this.x(d.values.start) : _this.x(0);
- } else {
- return _this.x(0);
- }
- })
- .attr('y', function(d) {
- if (d.arrange === 'nested') {
- var position = d.subcats.indexOf(d.key);
- var offset = position
- ? _this.y.rangeBand() / (d.subcats.length * 0.75) / position
- : _this.y.rangeBand();
- return _this.y(d.values.y) + (_this.y.rangeBand() - offset) / 2;
- } else if (d.arrange === 'grouped') {
- var _position2 = d.subcats.indexOf(d.key);
- return (
- _this.y(d.values.y) +
- _this.y.rangeBand() / d.subcats.length * _position2
- );
- } else {
- return _this.y(d.values.y);
- }
- })
- .attr('width', function(d) {
- return _this.x(d.values.x) - _this.x(0);
- })
- .attr('height', function(d) {
- if (config.y.type === 'quantile') {
- return 20;
- } else if (d.arrange === 'nested') {
- var position = d.subcats.indexOf(d.key);
- return position
- ? _this.y.rangeBand() / (d.subcats.length * 0.75) / position
- : _this.y.rangeBand();
- } else if (d.arrange === 'grouped') {
- return _this.y.rangeBand() / d.subcats.length;
- } else {
- return _this.y.rangeBand();
- }
- });
- } else if (['linear', 'log'].indexOf(config.x.type) > -1 && config.x.bin) {
- oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
+ //////////////////////////////////////////////////////////
+ // transformData(raw, mark) provides specifications and data for
+ // each set of marks. As such, it is called once for each
+ // item specified in the config.marks array.
+ //
+ // parameters
+ // raw - the raw data for use in the mark. Filters from controls
+ // are typically already applied.
+ // mark - a single mark object from config.marks
+ ////////////////////////////////////////////////////////
- oldBarGroupsTrans.remove();
+ function transformData(raw, mark) {
+ var _this = this;
- nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
- return 'bar-group ' + d.key;
- });
- nu_bar_groups.append('title');
+ //convenience mappings
+ var config = this.config;
+ var x_behavior = config.x.behavior || 'raw';
+ var y_behavior = config.y.behavior || 'raw';
+ var sublevel = mark.type === 'line'
+ ? config.x.column
+ : mark.type === 'bar' && mark.split ? mark.split : null;
+ var dateConvert = d3.time.format(config.date_format);
+ var totalOrder = void 0;
- bars = bar_groups.selectAll('rect').data(
- function(d) {
- return d.values instanceof Array ? d.values : [d];
- },
- function(d) {
- return d.key;
- }
+ ///////////////////////////////////////////////
+ // calcStartTotal() - method to calculate percentages in bars
+ //////////////////////////////////////////////
+ function calcStartTotal(e) {
+ var axis = config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)
+ ? 'y'
+ : 'x';
+ e.total = d3.sum(
+ e.values.map(function(m) {
+ return +m.values[axis];
+ })
);
+ var counter = 0;
+ e.values.forEach(function(v, i) {
+ if (config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)) {
+ v.values.y = mark.summarizeY === 'percent'
+ ? v.values.y / e.total
+ : v.values.y || 0;
+ counter += +v.values.y;
+ v.values.start = e.values[i - 1] ? counter : v.values.y;
+ } else {
+ v.values.x = mark.summarizeX === 'percent'
+ ? v.values.x / e.total
+ : v.values.x || 0;
+ v.values.start = counter;
+ counter += +v.values.x;
+ }
+ });
+ }
- var _exitBars2 = config.transitions ? bars.exit().transition() : bars.exit();
- _exitBars2.attr('y', this.y(0)).attr('height', 0).remove();
- bars
- .enter()
- .append('rect')
- .attr('class', function(d) {
- return 'wc-data-mark bar ' + d.key;
- })
- .style('clip-path', 'url(#' + this.id + ')')
- .attr('y', this.y(0))
- .attr('height', 0)
- .append('title');
+ function makeNest(entries, sublevel) {
+ var dom_xs = [];
+ var dom_ys = [];
+ var this_nest = d3.nest();
- bars
- .attr('shape-rendering', 'crispEdges')
- .attr('stroke', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- })
- .attr('fill', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
+ if (
+ (config.x.type === 'linear' && config.x.bin) ||
+ (config.y.type === 'linear' && config.y.bin)
+ ) {
+ var xy = config.x.type === 'linear' && config.x.bin ? 'x' : 'y';
+ var quant = d3.scale
+ .quantile()
+ .domain(
+ d3.extent(
+ entries.map(function(m) {
+ return +m[config[xy].column];
+ })
+ )
+ )
+ .range(d3.range(+config[xy].bin));
+
+ entries.forEach(function(e) {
+ return (e.wc_bin = quant(e[config[xy].column]));
});
- bars.each(function(d) {
- var mark = d3.select(this.parentNode.parentNode).datum();
- d.arrange = mark.split ? mark.arrange : null;
- d.subcats = config.legend.order
- ? config.legend.order.slice().reverse()
- : mark.values && mark.values[mark.split]
- ? mark.values[mark.split]
- : d3
- .set(
- rawData.map(function(m) {
- return m[mark.split];
- })
- )
- .values();
- d3.select(this).attr(mark.attributes);
- var parent = d3.select(this.parentNode).datum();
- var rangeSet = parent.key.split(',').map(function(m) {
- return +m;
+ this_nest.key(function(d) {
+ return quant.invertExtent(d.wc_bin);
});
- d.rangeLow = d3.min(rangeSet);
- d.rangeHigh = d3.max(rangeSet);
- d.tooltip = mark.tooltip;
- });
+ } else {
+ this_nest.key(function(d) {
+ return mark.per
+ .map(function(m) {
+ return d[m];
+ })
+ .join(' ');
+ });
+ }
- var _xformat2 = config.marks
- .map(function(m) {
- return m.summarizeX === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.x.format);
- var _yformat2 = config.marks
- .map(function(m) {
- return m.summarizeY === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.y.format);
- bars.select('title').text(function(d) {
- var tt = d.tooltip || '';
- return tt
- .replace(/\$x/g, _xformat2(d.values.x))
- .replace(/\$y/g, _yformat2(d.values.y))
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
+ if (sublevel) {
+ this_nest.key(function(d) {
+ return d[sublevel];
+ });
+ this_nest.sortKeys(function(a, b) {
+ return config.x.type === 'time'
+ ? d3.ascending(new Date(a), new Date(b))
+ : config.x.order
+ ? d3.ascending(config.x.order.indexOf(a), config.x.order.indexOf(b))
+ : sublevel === config.color_by && config.legend.order
+ ? d3.ascending(
+ config.legend.order.indexOf(a),
+ config.legend.order.indexOf(b)
+ )
+ : config.x.type === 'ordinal' || config.y.type === 'ordinal'
+ ? naturalSorter(a, b)
+ : d3.ascending(+a, +b);
+ });
+ }
+ this_nest.rollup(function(r) {
+ var obj = { raw: r };
+ var y_vals = r
+ .map(function(m) {
+ return m[config.y.column];
+ })
+ .sort(d3.ascending);
+ var x_vals = r
+ .map(function(m) {
+ return m[config.x.column];
+ })
+ .sort(d3.ascending);
+ obj.x = config.x.type === 'ordinal'
+ ? r[0][config.x.column]
+ : summarize(x_vals, mark.summarizeX);
+ obj.y = config.y.type === 'ordinal'
+ ? r[0][config.y.column]
+ : summarize(y_vals, mark.summarizeY);
+
+ obj.x_q25 = config.error_bars && config.y.type === 'ordinal'
+ ? d3.quantile(x_vals, 0.25)
+ : obj.x;
+ obj.x_q75 = config.error_bars && config.y.type === 'ordinal'
+ ? d3.quantile(x_vals, 0.75)
+ : obj.x;
+ obj.y_q25 = config.error_bars ? d3.quantile(y_vals, 0.25) : obj.y;
+ obj.y_q75 = config.error_bars ? d3.quantile(y_vals, 0.75) : obj.y;
+ dom_xs.push([obj.x_q25, obj.x_q75, obj.x]);
+ dom_ys.push([obj.y_q25, obj.y_q75, obj.y]);
+
+ if (mark.summarizeY === 'cumulative') {
+ var interm = entries.filter(function(f) {
+ return config.x.type === 'time'
+ ? new Date(f[config.x.column]) <= new Date(r[0][config.x.column])
+ : +f[config.x.column] <= +r[0][config.x.column];
});
- });
+ if (mark.per.length) {
+ interm = interm.filter(function(f) {
+ return f[mark.per[0]] === r[0][mark.per[0]];
+ });
+ }
- var _barsTrans2 = config.transitions ? bars.transition() : bars;
- _barsTrans2
- .attr('x', function(d) {
- return _this.x(d.rangeLow);
- })
- .attr('y', function(d) {
- if (d.arrange !== 'stacked') {
- return _this.y(d.values.y);
- } else {
- return _this.y(d.values.start);
+ var cumul = config.x.type === 'time'
+ ? interm.length
+ : d3.sum(
+ interm.map(function(m) {
+ return +m[config.y.column] || +m[config.y.column] === 0
+ ? +m[config.y.column]
+ : 1;
+ })
+ );
+ dom_ys.push([cumul]);
+ obj.y = cumul;
+ }
+ if (mark.summarizeX === 'cumulative') {
+ var _interm = entries.filter(function(f) {
+ return config.y.type === 'time'
+ ? new Date(f[config.y.column]) <= new Date(r[0][config.y.column])
+ : +f[config.y.column] <= +r[0][config.y.column];
+ });
+ if (mark.per.length) {
+ _interm = _interm.filter(function(f) {
+ return f[mark.per[0]] === r[0][mark.per[0]];
+ });
}
- })
- .attr('width', function(d) {
- return _this.x(d.rangeHigh) - _this.x(d.rangeLow);
- })
- .attr('height', function(d) {
- return _this.y(0) - _this.y(d.values.y);
- });
- } else if (
- ['linear', 'log'].indexOf(config.y.type) > -1 &&
- config.y.type === 'linear' &&
- config.y.bin
- ) {
- oldBarsTrans.attr('x', this.x(0)).attr('width', 0);
- oldBarGroupsTrans.remove();
+ dom_xs.push([_interm.length]);
+ obj.x = _interm.length;
+ }
- nu_bar_groups = bar_groups.enter().append('g').attr('class', function(d) {
- return 'bar-group ' + d.key;
+ return obj;
});
- nu_bar_groups.append('title');
- bars = bar_groups.selectAll('rect').data(
- function(d) {
- return d.values instanceof Array ? d.values : [d];
- },
- function(d) {
- return d.key;
- }
- );
+ var test = this_nest.entries(entries);
- var _exitBars3 = config.transitions ? bars.exit().transition() : bars.exit();
- _exitBars3.attr('x', this.x(0)).attr('width', 0).remove();
- bars
- .enter()
- .append('rect')
- .attr('class', function(d) {
- return 'wc-data-mark bar ' + d.key;
- })
- .style('clip-path', 'url(#' + this.id + ')')
- .attr('x', this.x(0))
- .attr('width', 0)
- .append('title');
+ var dom_x = d3.extent(d3.merge(dom_xs));
+ var dom_y = d3.extent(d3.merge(dom_ys));
- bars
- .attr('shape-rendering', 'crispEdges')
- .attr('stroke', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- })
- .attr('fill', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
+ if (sublevel && mark.type === 'bar' && mark.arrange === 'stacked') {
+ test.forEach(calcStartTotal);
+ if (config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)) {
+ dom_y = d3.extent(
+ test.map(function(m) {
+ return m.total;
+ })
+ );
+ }
+ if (config.y.type === 'ordinal' || (config.y.type === 'linear' && config.y.bin)) {
+ dom_x = d3.extent(
+ test.map(function(m) {
+ return m.total;
+ })
+ );
+ }
+ } else if (sublevel && mark.type === 'bar' && mark.split) {
+ test.forEach(calcStartTotal);
+ } else {
+ var axis = config.x.type === 'ordinal' ||
+ (config.x.type === 'linear' && config.x.bin)
+ ? 'y'
+ : 'x';
+ test.forEach(function(e) {
+ return (e.total = e.values[axis]);
});
+ }
- bars.each(function(d) {
- var mark = d3.select(this.parentNode.parentNode).datum();
- d.arrange = mark.split ? mark.arrange : null;
- d.subcats = config.legend.order
- ? config.legend.order.slice().reverse()
- : mark.values && mark.values[mark.split]
- ? mark.values[mark.split]
- : d3
- .set(
- rawData.map(function(m) {
- return m[mark.split];
- })
- )
- .values();
- var parent = d3.select(this.parentNode).datum();
- var rangeSet = parent.key.split(',').map(function(m) {
- return +m;
- });
- d.rangeLow = d3.min(rangeSet);
- d.rangeHigh = d3.max(rangeSet);
- d.tooltip = mark.tooltip;
+ if (
+ (config.x.sort === 'total-ascending' && config.x.type == 'ordinal') ||
+ (config.y.sort === 'total-descending' && config.y.type == 'ordinal')
+ ) {
+ totalOrder = test
+ .sort(function(a, b) {
+ return d3.ascending(a.total, b.total);
+ })
+ .map(function(m) {
+ return m.key;
+ });
+ } else if (
+ (config.x.sort === 'total-descending' && config.x.type == 'ordinal') ||
+ (config.y.sort === 'total-ascending' && config.y.type == 'ordinal')
+ ) {
+ totalOrder = test
+ .sort(function(a, b) {
+ return d3.descending(+a.total, +b.total);
+ })
+ .map(function(m) {
+ return m.key;
+ });
+ }
+
+ return { nested: test, dom_x: dom_x, dom_y: dom_y };
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DATA PREP
+ // prepare data based on the properties of the mark - drop missing records, etc
+ //////////////////////////////////////////////////////////////////////////////////
+
+ // only use data for the current mark
+ raw = mark.per && mark.per.length
+ ? raw.filter(function(f) {
+ return f[mark.per[0]];
+ })
+ : raw;
+
+ // Make sure data has x and y values
+ if (config.x.column) {
+ raw = raw.filter(function(f) {
+ return f[config.x.column] !== undefined;
});
+ }
+ if (config.y.column) {
+ raw = raw.filter(function(f) {
+ return f[config.y.column] !== undefined;
+ });
+ }
- var _xformat3 = config.marks
- .map(function(m) {
- return m.summarizeX === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.x.format);
- var _yformat3 = config.marks
- .map(function(m) {
- return m.summarizeY === 'percent';
- })
- .indexOf(true) > -1
- ? d3.format('0%')
- : d3.format(config.y.format);
- bars.select('title').text(function(d) {
- var tt = d.tooltip || '';
- return tt
- .replace(/\$x/g, _xformat3(d.values.x))
- .replace(/\$y/g, _yformat3(d.values.y))
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
- });
+ //check that x and y have the correct formats
+ if (config.x.type === 'time') {
+ raw = raw.filter(function(f) {
+ return f[config.x.column] instanceof Date
+ ? f[config.x.column]
+ : dateConvert.parse(f[config.x.column]);
+ });
+ raw.forEach(function(e) {
+ return (e[config.x.column] = e[config.x.column] instanceof Date
+ ? e[config.x.column]
+ : dateConvert.parse(e[config.x.column]));
+ });
+ }
+ if (config.y.type === 'time') {
+ raw = raw.filter(function(f) {
+ return f[config.y.column] instanceof Date
+ ? f[config.y.column]
+ : dateConvert.parse(f[config.y.column]);
+ });
+ raw.forEach(function(e) {
+ return (e[config.y.column] = e[config.y.column] instanceof Date
+ ? e[config.y.column]
+ : dateConvert.parse(e[config.y.column]));
});
+ }
- var _barsTrans3 = config.transitions ? bars.transition() : bars;
- _barsTrans3
- .attr('x', function(d) {
- if (d.arrange === 'stacked') {
- return _this.x(d.values.start);
- } else {
- return _this.x(0);
- }
- })
- .attr('y', function(d) {
- return _this.y(d.rangeHigh);
- })
- .attr('width', function(d) {
- return _this.x(d.values.x);
- })
- .attr('height', function(d) {
- return _this.y(d.rangeLow) - _this.y(d.rangeHigh);
- });
- } else {
- oldBarsTrans.attr('y', this.y(0)).attr('height', 0);
- oldBarGroupsTrans.remove();
- bar_supergroups.remove();
+ if ((config.x.type === 'linear' || config.x.type === 'log') && config.x.column) {
+ raw = raw.filter(function(f) {
+ return mark.summarizeX !== 'count' && mark.summarizeX !== 'percent'
+ ? +f[config.x.column] || +f[config.x.column] === 0
+ : f;
+ });
+ }
+ if ((config.y.type === 'linear' || config.y.type === 'log') && config.y.column) {
+ raw = raw.filter(function(f) {
+ return mark.summarizeY !== 'count' && mark.summarizeY !== 'percent'
+ ? +f[config.y.column] || +f[config.y.column] === 0
+ : f;
+ });
}
- //Link to the d3.selection from the data
- bar_supergroups.each(function(d) {
- d.supergroup = d3.select(this);
- d.groups = d.supergroup.selectAll('.bar-group');
- });
- }
+ //prepare nested data required for bar charts
+ var raw_nest = void 0;
+ if (mark.type === 'bar') {
+ raw_nest = mark.arrange !== 'stacked' ? makeNest(raw, sublevel) : makeNest(raw);
+ } else if (mark.summarizeX === 'count' || mark.summarizeY === 'count') {
+ raw_nest = makeNest(raw);
+ }
+
+ // Get the domain for the mark based on the raw data
+ var raw_dom_x = mark.summarizeX === 'cumulative'
+ ? [0, raw.length]
+ : config.x.type === 'ordinal'
+ ? d3
+ .set(
+ raw.map(function(m) {
+ return m[config.x.column];
+ })
+ )
+ .values()
+ .filter(function(f) {
+ return f;
+ })
+ : mark.split && mark.arrange !== 'stacked'
+ ? d3.extent(
+ d3.merge(
+ raw_nest.nested.map(function(m) {
+ return m.values.map(function(p) {
+ return p.values.raw.length;
+ });
+ })
+ )
+ )
+ : mark.summarizeX === 'count'
+ ? d3.extent(
+ raw_nest.nested.map(function(m) {
+ return m.values.raw.length;
+ })
+ )
+ : d3.extent(
+ raw
+ .map(function(m) {
+ return +m[config.x.column];
+ })
+ .filter(function(f) {
+ return +f || +f === 0;
+ })
+ );
+
+ var raw_dom_y = mark.summarizeY === 'cumulative'
+ ? [0, raw.length]
+ : config.y.type === 'ordinal'
+ ? d3
+ .set(
+ raw.map(function(m) {
+ return m[config.y.column];
+ })
+ )
+ .values()
+ .filter(function(f) {
+ return f;
+ })
+ : mark.split && mark.arrange !== 'stacked'
+ ? d3.extent(
+ d3.merge(
+ raw_nest.nested.map(function(m) {
+ return m.values.map(function(p) {
+ return p.values.raw.length;
+ });
+ })
+ )
+ )
+ : mark.summarizeY === 'count'
+ ? d3.extent(
+ raw_nest.nested.map(function(m) {
+ return m.values.raw.length;
+ })
+ )
+ : d3.extent(
+ raw
+ .map(function(m) {
+ return +m[config.y.column];
+ })
+ .filter(function(f) {
+ return +f || +f === 0;
+ })
+ );
- function drawLines(marks) {
- var _this = this;
+ var filtered = raw;
- var config = this.config;
- var line = d3.svg
- .line()
- .interpolate(config.interpolate)
- .x(function(d) {
- return config.x.type === 'linear' || config.x.type == 'log'
- ? _this.x(+d.values.x)
- : config.x.type === 'time'
- ? _this.x(new Date(d.values.x))
- : _this.x(d.values.x) + _this.x.rangeBand() / 2;
- })
- .y(function(d) {
- return config.y.type === 'linear' || config.y.type == 'log'
- ? _this.y(+d.values.y)
- : config.y.type === 'time'
- ? _this.y(new Date(d.values.y))
- : _this.y(d.values.y) + _this.y.rangeBand() / 2;
+ var filt1_xs = [];
+ var filt1_ys = [];
+ if (this.filters.length) {
+ this.filters.forEach(function(e) {
+ filtered = filtered.filter(function(d) {
+ return e.val === 'All'
+ ? d
+ : e.val instanceof Array
+ ? e.val.indexOf(d[e.col]) > -1
+ : d[e.col] === e.val;
+ });
});
+ //get domain for all non-All values of first filter
+ if (config.x.behavior === 'firstfilter' || config.y.behavior === 'firstfilter') {
+ this.filters[0].choices
+ .filter(function(f) {
+ return f !== 'All';
+ })
+ .forEach(function(e) {
+ var perfilter = raw.filter(function(f) {
+ return f[_this.filters[0].col] === e;
+ });
+ var filt_nested = makeNest(perfilter, sublevel);
+ filt1_xs.push(filt_nested.dom_x);
+ filt1_ys.push(filt_nested.dom_y);
+ });
+ }
+ }
- var line_supergroups = this.svg.selectAll('.line-supergroup').data(marks, function(d, i) {
- return i + '-' + d.per.join('-');
- });
-
- line_supergroups.enter().append('g').attr('class', function(d) {
- return 'supergroup line-supergroup ' + d.id;
- });
-
- line_supergroups.exit().remove();
+ //filter on mark-specific instructions
+ if (mark.values) {
+ var _loop = function _loop(a) {
+ filtered = filtered.filter(function(f) {
+ return mark.values[a].indexOf(f[a]) > -1;
+ });
+ };
- var line_grps = line_supergroups.selectAll('.line').data(
- function(d) {
- return d.data;
- },
- function(d) {
- return d.key;
+ for (var a in mark.values) {
+ _loop(a);
}
- );
- line_grps.exit().remove();
- var nu_line_grps = line_grps.enter().append('g').attr('class', function(d) {
- return d.key + ' line';
- });
- nu_line_grps.append('path');
- nu_line_grps.append('title');
+ }
+ var filt1_dom_x = d3.extent(d3.merge(filt1_xs));
+ var filt1_dom_y = d3.extent(d3.merge(filt1_ys));
- var linePaths = line_grps
- .select('path')
- .attr('class', 'wc-data-mark')
- .datum(function(d) {
- return d.values;
- })
- .attr('stroke', function(d) {
- return _this.colorScale(d[0].values.raw[0][config.color_by]);
- })
- .attr(
- 'stroke-width',
- config.stroke_width ? config.stroke_width : config.flex_stroke_width
- )
- .attr('stroke-linecap', 'round')
- .attr('fill', 'none');
- var linePathsTrans = config.transitions ? linePaths.transition() : linePaths;
- linePathsTrans.attr('d', line);
+ var current_nested = makeNest(filtered, sublevel);
- line_grps.each(function(d) {
- var mark = d3.select(this.parentNode).datum();
- d.tooltip = mark.tooltip;
- d3.select(this).select('path').attr(mark.attributes);
- });
+ var flex_dom_x = current_nested.dom_x;
+ var flex_dom_y = current_nested.dom_y;
- line_grps.select('title').text(function(d) {
- var tt = d.tooltip || '';
- var xformat = config.x.summary === 'percent'
- ? d3.format('0%')
- : d3.format(config.x.format);
- var yformat = config.y.summary === 'percent'
- ? d3.format('0%')
- : d3.format(config.y.format);
- return tt
- .replace(/\$x/g, xformat(d.values.x))
- .replace(/\$y/g, yformat(d.values.y))
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values[0].values.raw[0][orig];
- });
- });
+ if (mark.type === 'bar') {
+ if (config.y.type === 'ordinal' && mark.summarizeX === 'count') {
+ config.x.domain = config.x.domain ? [0, config.x.domain[1]] : [0, null];
+ } else if (config.x.type === 'ordinal' && mark.summarizeY === 'count') {
+ config.y.domain = config.y.domain ? [0, config.y.domain[1]] : [0, null];
+ }
+ }
- //Link to the d3.selection from the data
- line_supergroups.each(function(d) {
- d.supergroup = d3.select(this);
- d.groups = d.supergroup.selectAll('g.line');
- d.paths = d.groups.select('path');
- });
- return line_grps;
- }
+ //several criteria must be met in order to use the 'firstfilter' domain
+ var nonall = Boolean(
+ this.filters.length &&
+ this.filters[0].val !== 'All' &&
+ this.filters.slice(1).filter(function(f) {
+ return f.val === 'All';
+ }).length ===
+ this.filters.length - 1
+ );
- function drawPoints(marks) {
- var _this = this;
+ var pre_x_dom = !this.filters.length
+ ? flex_dom_x
+ : x_behavior === 'raw'
+ ? raw_dom_x
+ : nonall && x_behavior === 'firstfilter' ? filt1_dom_x : flex_dom_x;
+ var pre_y_dom = !this.filters.length
+ ? flex_dom_y
+ : y_behavior === 'raw'
+ ? raw_dom_y
+ : nonall && y_behavior === 'firstfilter' ? filt1_dom_y : flex_dom_y;
- var config = this.config;
+ var x_dom = config.x_dom
+ ? config.x_dom
+ : config.x.type === 'ordinal' && config.x.behavior === 'flex'
+ ? d3
+ .set(
+ filtered.map(function(m) {
+ return m[config.x.column];
+ })
+ )
+ .values()
+ : config.x.type === 'ordinal'
+ ? d3
+ .set(
+ raw.map(function(m) {
+ return m[config.x.column];
+ })
+ )
+ .values()
+ : config.x_from0 ? [0, d3.max(pre_x_dom)] : pre_x_dom;
- var point_supergroups = this.svg.selectAll('.point-supergroup').data(marks, function(d, i) {
- return i + '-' + d.per.join('-');
- });
+ var y_dom = config.y_dom
+ ? config.y_dom
+ : config.y.type === 'ordinal' && config.y.behavior === 'flex'
+ ? d3
+ .set(
+ filtered.map(function(m) {
+ return m[config.y.column];
+ })
+ )
+ .values()
+ : config.y.type === 'ordinal'
+ ? d3
+ .set(
+ raw.map(function(m) {
+ return m[config.y.column];
+ })
+ )
+ .values()
+ : config.y_from0 ? [0, d3.max(pre_y_dom)] : pre_y_dom;
- point_supergroups.enter().append('g').attr('class', function(d) {
- return 'supergroup point-supergroup ' + d.id;
- });
+ if (config.x.domain && (config.x.domain[0] || config.x.domain[0] === 0)) {
+ x_dom[0] = config.x.domain[0];
+ }
+ if (config.x.domain && (config.x.domain[1] || config.x.domain[1] === 0)) {
+ x_dom[1] = config.x.domain[1];
+ }
+ if (config.y.domain && (config.y.domain[0] || config.y.domain[0] === 0)) {
+ y_dom[0] = config.y.domain[0];
+ }
+ if (config.y.domain && (config.y.domain[1] || config.y.domain[1] === 0)) {
+ y_dom[1] = config.y.domain[1];
+ }
- point_supergroups.exit().remove();
+ if (config.x.type === 'ordinal' && !config.x.order) {
+ config.x.order = totalOrder;
+ }
+ if (config.y.type === 'ordinal' && !config.y.order) {
+ config.y.order = totalOrder;
+ }
- var points = point_supergroups.selectAll('.point').data(
- function(d) {
- return d.data;
- },
- function(d) {
- return d.key;
- }
- );
- var oldPoints = points.exit();
+ this.current_data = current_nested.nested;
- var oldPointsTrans = config.transitions
- ? oldPoints.selectAll('circle').transition()
- : oldPoints.selectAll('circle');
- oldPointsTrans.attr('r', 0);
+ this.events.onDatatransform.call(this);
- var oldPointGroupTrans = config.transitions ? oldPoints.transition() : oldPoints;
- oldPointGroupTrans.remove();
+ return { config: mark, data: current_nested.nested, x_dom: x_dom, y_dom: y_dom };
+ }
- var nupoints = points.enter().append('g').attr('class', function(d) {
- return d.key + ' point';
- });
- nupoints.append('circle').attr('class', 'wc-data-mark').attr('r', 0);
- nupoints.append('title');
- //static attributes
- points
- .select('circle')
- .attr(
- 'fill-opacity',
- config.fill_opacity || config.fill_opacity === 0 ? config.fill_opacity : 0.6
- )
- .attr('fill', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
+ function updateDataMarks() {
+ this.drawBars(
+ this.marks.filter(function(f) {
+ return f.type === 'bar';
})
- .attr('stroke', function(d) {
- return _this.colorScale(d.values.raw[0][config.color_by]);
- });
- //attach mark info
- points.each(function(d) {
- var mark = d3.select(this.parentNode).datum();
- d.mark = mark;
- d3.select(this).select('circle').attr(mark.attributes);
- });
- //animated attributes
- var pointsTrans = config.transitions
- ? points.select('circle').transition()
- : points.select('circle');
- pointsTrans
- .attr('r', function(d) {
- return d.mark.radius || config.flex_point_size;
+ );
+ this.drawLines(
+ this.marks.filter(function(f) {
+ return f.type === 'line';
})
- .attr('cx', function(d) {
- var x_pos = _this.x(d.values.x) || 0;
- return config.x.type === 'ordinal' ? x_pos + _this.x.rangeBand() / 2 : x_pos;
+ );
+ this.drawPoints(
+ this.marks.filter(function(f) {
+ return f.type === 'circle';
})
- .attr('cy', function(d) {
- var y_pos = _this.y(d.values.y) || 0;
- return config.y.type === 'ordinal' ? y_pos + _this.y.rangeBand() / 2 : y_pos;
- });
-
- points.select('title').text(function(d) {
- var tt = d.mark.tooltip || '';
- var xformat = config.x.summary === 'percent'
- ? d3.format('0%')
- : config.x.type === 'time'
- ? d3.time.format(config.x.format)
- : d3.format(config.x.format);
- var yformat = config.y.summary === 'percent'
- ? d3.format('0%')
- : config.y.type === 'time'
- ? d3.time.format(config.y.format)
- : d3.format(config.y.format);
- return tt
- .replace(
- /\$x/g,
- config.x.type === 'time' ? xformat(new Date(d.values.x)) : xformat(d.values.x)
- )
- .replace(
- /\$y/g,
- config.y.type === 'time' ? yformat(new Date(d.values.y)) : yformat(d.values.y)
- )
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
- });
- });
-
- //Link to the d3.selection from the data
- point_supergroups.each(function(d) {
- d.supergroup = d3.select(this);
- d.groups = d.supergroup.selectAll('g.point');
- d.circles = d.groups.select('circle');
- });
+ );
+ this.drawText(
+ this.marks.filter(function(f) {
+ return f.type === 'text';
+ })
+ );
- return points;
+ this.marks.supergroups = this.svg.selectAll('g.supergroup');
}
- function drawText(marks) {
- var _this = this;
-
+ function xScaleAxis(max_range, domain, type) {
+ if (max_range === undefined) {
+ max_range = this.plot_width;
+ }
+ if (domain === undefined) {
+ domain = this.x_dom;
+ }
+ if (type === undefined) {
+ type = this.config.x.type;
+ }
var config = this.config;
+ var x = void 0;
- var textSupergroups = this.svg.selectAll('.text-supergroup').data(marks, function(d, i) {
- return i + '-' + d.per.join('-');
- });
-
- textSupergroups.enter().append('g').attr('class', function(d) {
- return 'supergroup text-supergroup ' + d.id;
- });
-
- textSupergroups.exit().remove();
+ if (type === 'log') {
+ x = d3.scale.log();
+ } else if (type === 'ordinal') {
+ x = d3.scale.ordinal();
+ } else if (type === 'time') {
+ x = d3.time.scale();
+ } else {
+ x = d3.scale.linear();
+ }
- var texts = textSupergroups.selectAll('.text').data(
- function(d) {
- return d.data;
- },
- function(d) {
- return d.key;
- }
- );
- var oldTexts = texts.exit();
+ x.domain(domain);
- // don't need to transition position of outgoing text
- // const oldTextsTrans = config.transitions ? oldTexts.selectAll('text').transition() : oldTexts.selectAll('text');
+ if (type === 'ordinal') {
+ x.rangeBands([0, +max_range], config.padding, config.outer_pad);
+ } else {
+ x.range([0, +max_range]).clamp(Boolean(config.x.clamp));
+ }
- var oldTextGroupTrans = config.transitions ? oldTexts.transition() : oldTexts;
- oldTextGroupTrans.remove();
+ var xFormat = config.x.format
+ ? config.x.format
+ : config.marks
+ .map(function(m) {
+ return m.summarizeX === 'percent';
+ })
+ .indexOf(true) > -1
+ ? '0%'
+ : type === 'time' ? '%x' : '.0f';
+ var tick_count = Math.max(2, Math.min(max_range / 80, 8));
+ var xAxis = d3.svg
+ .axis()
+ .scale(x)
+ .orient(config.x.location)
+ .ticks(tick_count)
+ .tickFormat(
+ type === 'ordinal'
+ ? null
+ : type === 'time' ? d3.time.format(xFormat) : d3.format(xFormat)
+ )
+ .tickValues(config.x.ticks ? config.x.ticks : null)
+ .innerTickSize(6)
+ .outerTickSize(3);
- var nutexts = texts.enter().append('g').attr('class', function(d) {
- return d.key + ' text';
- });
- nutexts.append('text').attr('class', 'wc-data-mark');
- // don't need to set initial location for incoming text
+ this.svg.select('g.x.axis').attr('class', 'x axis ' + type);
+ this.x = x;
+ this.xAxis = xAxis;
+ }
- // attach mark info
- function attachMarks(d) {
- d.mark = d3.select(this.parentNode).datum();
- d3.select(this).select('text').attr(d.mark.attributes);
+ function yScaleAxis(max_range, domain, type) {
+ if (max_range === undefined) {
+ max_range = this.plot_height;
+ }
+ if (domain === undefined) {
+ domain = this.y_dom;
+ }
+ if (type === undefined) {
+ type = this.config.y.type;
+ }
+ var config = this.config;
+ var y = void 0;
+ if (type === 'log') {
+ y = d3.scale.log();
+ } else if (type === 'ordinal') {
+ y = d3.scale.ordinal();
+ } else if (type === 'time') {
+ y = d3.time.scale();
+ } else {
+ y = d3.scale.linear();
}
- texts.each(attachMarks);
-
- // parse text like tooltips
- texts.select('text').text(function(d) {
- var tt = d.mark.text || '';
- var xformat = config.x.summary === 'percent'
- ? d3.format('0%')
- : config.x.type === 'time'
- ? d3.time.format(config.x.format)
- : d3.format(config.x.format);
- var yformat = config.y.summary === 'percent'
- ? d3.format('0%')
- : config.y.type === 'time'
- ? d3.time.format(config.y.format)
- : d3.format(config.y.format);
- return tt
- .replace(
- /\$x/g,
- config.x.type === 'time' ? xformat(new Date(d.values.x)) : xformat(d.values.x)
- )
- .replace(
- /\$y/g,
- config.y.type === 'time' ? yformat(new Date(d.values.y)) : yformat(d.values.y)
- )
- .replace(/\[(.+?)\]/g, function(str, orig) {
- return d.values.raw[0][orig];
- });
- });
- // animated attributes
- var textsTrans = config.transitions
- ? texts.select('text').transition()
- : texts.select('text');
- textsTrans
- .attr('x', function(d) {
- var xPos = _this.x(d.values.x) || 0;
- return config.x.type === 'ordinal' ? xPos + _this.x.rangeBand() / 2 : xPos;
- })
- .attr('y', function(d) {
- var yPos = _this.y(d.values.y) || 0;
- return config.y.type === 'ordinal' ? yPos + _this.y.rangeBand() / 2 : yPos;
- });
- //add a reference to the selection from it's data
- textSupergroups.each(function(d) {
- d.supergroup = d3.select(this);
- d.groups = d.supergroup.selectAll('g.text');
- d.texts = d.groups.select('text');
- });
- return texts;
- }
- function destroy() {
- var destroyControls = arguments.length > 0 && arguments[0] !== undefined
- ? arguments[0]
- : true;
+ y.domain(domain);
- //run onDestroy callback
- this.events.onDestroy.call(this);
+ if (type === 'ordinal') {
+ y.rangeBands([+max_range, 0], config.padding, config.outer_pad);
+ } else {
+ y.range([+max_range, 0]).clamp(Boolean(config.y_clamp));
+ }
- //remove resize event listener
- var context = this;
- d3.select(window).on('resize.' + context.element + context.id, null);
+ var yFormat = config.y.format
+ ? config.y.format
+ : config.marks
+ .map(function(m) {
+ return m.summarizeY === 'percent';
+ })
+ .indexOf(true) > -1
+ ? '0%'
+ : '.0f';
+ var tick_count = Math.max(2, Math.min(max_range / 80, 8));
+ var yAxis = d3.svg
+ .axis()
+ .scale(y)
+ .orient('left')
+ .ticks(tick_count)
+ .tickFormat(
+ type === 'ordinal'
+ ? null
+ : type === 'time' ? d3.time.format(yFormat) : d3.format(yFormat)
+ )
+ .tickValues(config.y.ticks ? config.y.ticks : null)
+ .innerTickSize(6)
+ .outerTickSize(3);
- //destroy controls
- if (destroyControls && this.controls) {
- this.controls.destroy();
- }
+ this.svg.select('g.y.axis').attr('class', 'y axis ' + type);
- //unmount chart wrapper
- this.wrap.remove();
+ this.y = y;
+ this.yAxis = yAxis;
}
var chartProto = {
@@ -3277,42 +3157,26 @@
: clone(this.data.raw);
}
- function updateDataObject() {
- this.data.raw = this.data.passed;
- this.data.filtered = this.data.passed;
- this.config.activePage = 0;
- this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
- this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
- }
-
- function applySearchTerm(data) {
+ function applySearchTerm() {
var _this = this;
- if (this.searchable.searchTerm) {
- //Determine which rows contain input text.
- this.data.searched = this.data.filtered.filter(function(d) {
- var match = false;
+ //Determine which rows contain input text.
+ this.data.searched = this.data.filtered.filter(function(d) {
+ var match = false;
- Object.keys(d)
- .filter(function(key) {
- return _this.config.cols.indexOf(key) > -1;
- })
- .forEach(function(var_name) {
- if (match === false) {
- var cellText = '' + d[var_name];
- match =
- cellText.toLowerCase().indexOf(_this.searchable.searchTerm) > -1;
- }
- });
+ Object.keys(d)
+ .filter(function(key) {
+ return _this.config.cols.indexOf(key) > -1;
+ })
+ .forEach(function(var_name) {
+ if (match === false) {
+ var cellText = '' + d[var_name];
+ match = cellText.toLowerCase().indexOf(_this.searchable.searchTerm) > -1;
+ }
+ });
- return match;
- });
- this.data.processing = this.data.searched;
- } else {
- //Otherwise delete previously searched data and set data to filtered data.
- delete this.data.searched;
- this.data.processing = this.data.filtered;
- }
+ return match;
+ });
}
/*------------------------------------------------------------------------------------------------\
@@ -3347,7 +3211,26 @@
// Hide method from for-in loops
Object.defineProperty(Array.prototype, 'equals', { enumerable: false });
- function checkFilters() {
+ function draw$1(passed_data) {
+ var _this = this;
+
+ var context = this,
+ config = this.config,
+ table = this.table;
+
+ //Apply filters if data is not passed to table.draw().
+ if (!passed_data) {
+ applyFilters.call(this);
+ } else {
+ //Otherwise update data object.
+ this.data.raw = passed_data;
+ this.data.filtered = passed_data;
+ this.config.activePage = 0;
+ this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
+ this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
+ }
+
+ //Compare current filter settings to previous filter settings, if any.
if (this.filters) {
this.currentFilters = this.filters.map(function(filter) {
return filter.val;
@@ -3362,11 +3245,28 @@
this.previousFilters = this.currentFilters;
}
- }
- function updateTableHeaders() {
- var _this = this;
+ var data = void 0;
+
+ //Filter data on search term if it exists and set data to searched data.
+ if (this.searchable.searchTerm) {
+ applySearchTerm.call(this);
+ data = this.data.searched;
+ } else {
+ //Otherwise delete previously searched data and set data to filtered data.
+ delete this.data.searched;
+ data = this.data.filtered;
+ }
+
+ this.searchable.wrap
+ .select('.nNrecords')
+ .text(
+ data.length === this.data.raw.length
+ ? this.data.raw.length + ' records displayed'
+ : data.length + '/' + this.data.raw.length + ' records displayed'
+ );
+ //update table header
this.thead_cells = this.thead
.select('tr')
.selectAll('th')
@@ -3375,6 +3275,7 @@
});
this.thead_cells.exit().remove();
this.thead_cells.enter().append('th');
+
this.thead_cells
.sort(function(a, b) {
return _this.config.headers.indexOf(a) - _this.config.headers.indexOf(b);
@@ -3385,44 +3286,87 @@
.text(function(d) {
return d;
});
- }
- function drawTableBody() {
- var _this = this;
+ //Clear table body rows.
+ this.tbody.selectAll('tr').remove();
- var table = this;
+ //Print a note that no data was selected for empty tables.
+ if (data.length === 0) {
+ this.tbody
+ .append('tr')
+ .classed('no-data', true)
+ .append('td')
+ .attr('colspan', this.config.cols.length)
+ .text('No data selected.');
- //Define table body rows.
- var rows = this.tbody.selectAll('tr').data(this.data.processing).enter().append('tr');
+ //Add export.
+ if (this.config.exportable)
+ this.config.exports.forEach(function(fmt) {
+ _this.exportable.exports[fmt].call(_this, data);
+ });
- //Define table body cells.
- var cells = rows.selectAll('td').data(function(d) {
- return _this.config.cols.map(function(key) {
- return { col: key, text: d[key] };
- });
- });
- cells.exit().remove();
- cells.enter().append('td');
- cells
- .sort(function(a, b) {
- return _this.config.cols.indexOf(a.col) - _this.config.cols.indexOf(b.col);
- })
- .attr('class', function(d) {
- return d.col;
- })
- .each(function(d) {
- var cell = d3.select(this);
+ //Add pagination.
+ if (this.config.pagination) this.pagination.addPagination.call(this, data);
+ } else {
+ //Sort data.
+ if (this.config.sortable) {
+ this.thead.selectAll('th').on('click', function(header) {
+ context.sortable.onClick.call(context, this, header);
+ });
- //Apply text in data as html or as plain text.
- if (table.config.as_html) {
- cell.html(d.text);
- } else {
- cell.text(d.text);
- }
+ if (this.sortable.order.length) this.sortable.sortData.call(this, data);
+ }
+
+ //Bind table filtered/searched data to table container.
+ this.wrap.datum(clone(data));
+
+ //Add export.
+ if (this.config.exportable)
+ this.config.exports.forEach(function(fmt) {
+ _this.exportable.exports[fmt].call(_this, data);
+ });
+
+ //Add pagination.
+ if (this.config.pagination) {
+ this.pagination.addPagination.call(this, data);
+
+ //Apply pagination.
+ data = data.filter(function(d, i) {
+ return _this.config.startIndex <= i && i < _this.config.endIndex;
+ });
+ }
+
+ //Define table body rows.
+ var rows = this.tbody.selectAll('tr').data(data).enter().append('tr');
+
+ //Define table body cells.
+ var cells = rows.selectAll('td').data(function(d) {
+ return _this.config.cols.map(function(key) {
+ return { col: key, text: d[key] };
+ });
});
- }
+ cells.exit().remove();
+ cells.enter().append('td');
+ cells
+ .sort(function(a, b) {
+ return _this.config.cols.indexOf(a.col) - _this.config.cols.indexOf(b.col);
+ })
+ .attr('class', function(d) {
+ return d.col;
+ })
+ .each(function(d) {
+ var cell = d3.select(this);
+
+ //Apply text in data as html or as plain text.
+ if (config.as_html) {
+ cell.html(d.text);
+ } else {
+ cell.text(d.text);
+ }
+ });
+ }
- function dynamicLayout() {
+ //Alter table layout if table is narrower than table top or bottom.
var widths = {
table: this.table.select('thead').node().offsetWidth,
top:
@@ -3460,114 +3404,14 @@
.style({
display: 'inline-block',
float: function float() {
- return select(this).classed('searchable-container') ||
- select(this).classed('pagination-container')
+ return d3.select(this).classed('searchable-container') ||
+ d3.select(this).classed('pagination-container')
? 'right'
: null;
},
clear: null
});
}
- }
-
- function draw$1(passed_data) {
- var _this = this;
-
- var table = this;
- var config = this.config;
-
- this.data.passed = passed_data; // make passed data available on preprocess
- this.events.onPreprocess.call(this);
-
- if (!passed_data)
- //Apply filters if data is not passed to table.draw().
- applyFilters.call(this);
- else
- //Otherwise update data object.
- updateDataObject.call(this);
-
- //Compare current filter settings to previous filter settings, if any.
- checkFilters.call(this);
-
- //Filter data on search term if it exists and set data to searched data.
- applySearchTerm.call(this);
-
- this.searchable.wrap
- .select('.nNrecords')
- .text(
- this.data.processing.length === this.data.raw.length
- ? this.data.raw.length + ' records displayed'
- : this.data.processing.length +
- '/' +
- this.data.raw.length +
- ' records displayed'
- );
-
- //Update table headers.
- updateTableHeaders.call(this);
-
- //Clear table body rows.
- this.tbody.selectAll('tr').remove();
-
- //Print a note that no data was selected for empty tables.
- if (this.data.processing.length === 0) {
- this.tbody
- .append('tr')
- .classed('no-data', true)
- .append('td')
- .attr('colspan', this.config.cols.length)
- .text('No data selected.');
-
- //Bind table filtered/searched data to table container.
- this.data.current = clone(this.data.processing);
- this.table.datum(this.table.current);
-
- //Add export.
- if (this.config.exportable)
- this.config.exports.forEach(function(fmt) {
- _this.exportable.exports[fmt].call(_this, _this.data.processing);
- });
-
- //Add pagination.
- if (this.config.pagination)
- this.pagination.addPagination.call(this, this.data.processing);
- } else {
- //Sort data.
- if (this.config.sortable) {
- this.thead.selectAll('th').on('click', function(header) {
- table.sortable.onClick.call(table, this, header);
- });
-
- if (this.sortable.order.length)
- this.sortable.sortData.call(this, this.data.processing);
- }
-
- //Bind table filtered/searched data to table container.
- this.data.current = clone(this.data.processing);
- this.table.datum(this.data.current);
-
- //Add export.
- if (this.config.exportable)
- this.config.exports.forEach(function(fmt) {
- _this.exportable.exports[fmt].call(_this, _this.data.processing);
- });
-
- //Add pagination.
- if (this.config.pagination) {
- this.pagination.addPagination.call(this, this.data.processing);
-
- //Apply pagination.
- this.data.processing = this.data.processing.filter(function(d, i) {
- return _this.config.startIndex <= i && i < _this.config.endIndex;
- });
- }
-
- //Define table body rows.
- drawTableBody.call(this);
- }
-
- //Alter table layout if table is narrower than table top or bottom.
- dynamicLayout.call(this);
this.events.onDraw.call(this);
}
@@ -3630,14 +3474,16 @@
var CSVarray = [];
- //add headers to CSV array
- var headers = this.config.headers.map(function(header) {
- return '"' + header.replace(/"/g, '""') + '"';
- });
- CSVarray.push(headers);
-
- //add rows to CSV array
data.forEach(function(d, i) {
+ //add headers to CSV array
+ if (i === 0) {
+ var headers = _this.config.headers.map(function(header) {
+ return '"' + header.replace(/"/g, '""') + '"';
+ });
+ CSVarray.push(headers);
+ }
+
+ //add rows to CSV array
var row = _this.config.cols.map(function(col) {
var value = d[col];
@@ -4388,18 +4234,28 @@
thisTable.required_cols = [];
- thisTable.wrap = d3.select(thisTable.div).append('div').datum(thisTable);
+ thisTable.wrap = d3.select(thisTable.div).append('div');
thisTable.events = {
onInit: function onInit() {},
onLayout: function onLayout() {},
onPreprocess: function onPreprocess() {},
+ onDatatransform: function onDatatransform() {},
onDraw: function onDraw() {},
+ onResize: function onResize() {},
onDestroy: function onDestroy() {}
};
thisTable.on = function(event, callback) {
- var possible_events = ['init', 'layout', 'preprocess', 'draw', 'destroy'];
+ var possible_events = [
+ 'init',
+ 'layout',
+ 'preprocess',
+ 'datatransform',
+ 'draw',
+ 'resize',
+ 'destroy'
+ ];
if (possible_events.indexOf(event) < 0) {
return;
}
@@ -4414,13 +4270,11 @@
function multiply(chart, data, split_by, order) {
var test = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
- chart.wrap.classed('wc-layout wc-small-multiples', true).classed('wc-chart', false);
-
- //Define container for legend that overrides multiples' legends.
- chart.master_legend = chart.wrap.append('ul').attr('class', 'legend');
- chart.master_legend.append('span').classed('legend-title', true);
-
- //Instantiate multiples array.
+ var config = chart.config;
+ var wrap = chart.wrap
+ .classed('wc-layout wc-small-multiples', true)
+ .classed('wc-chart', false);
+ var master_legend = wrap.append('ul').attr('class', 'legend');
chart.multiples = [];
function goAhead(data) {
@@ -4440,17 +4294,16 @@
});
}
split_vals.forEach(function(e) {
- var mchart = createChart(chart.wrap.node(), chart.config, chart.controls);
+ var mchart = createChart(chart.wrap.node(), config, chart.controls);
chart.multiples.push(mchart);
mchart.parent = chart;
mchart.events = chart.events;
- mchart.legend = chart.master_legend;
+ mchart.legend = master_legend;
mchart.filters.unshift({ col: split_by, val: e, choices: split_vals });
mchart.wrap.insert('span', 'svg').attr('class', 'wc-chart-title').text(e);
mchart.init(data, test);
});
}
-
goAhead(data);
}
diff --git a/build/webcharts.min.js b/build/webcharts.min.js
index 8653464..dbeb366 100644
--- a/build/webcharts.min.js
+++ b/build/webcharts.min.js
@@ -1,3 +1,3 @@
-(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory(require("d3")):typeof define==="function"&&define.amd?define(["d3"],factory):global.webCharts=factory(global.d3)})(this,function(d3){"use strict";var version="1.11.0";function init(data){var _this=this;var test=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;if(d3.select(this.div).select(".loader").empty()){d3.select(this.div).insert("div",":first-child").attr("class","loader").selectAll(".blockG").data(d3.range(8)).enter().append("div").attr("class",function(d){return"blockG rotate"+(d+1)})}this.wrap.attr("class","wc-chart");this.setDefaults();this.raw_data=data;this.initial_data=data;var startup=function startup(data){if(_this.controls){_this.controls.targets.push(_this);if(!_this.controls.ready){_this.controls.init(_this.raw_data)}else{_this.controls.layout()}}var visible=d3.select(_this.div).property("offsetWidth")>0||test;if(!visible){console.warn("The chart cannot be initialized inside an element with 0 width. The chart will be initialized as soon as the container element is given a width > 0.");var onVisible=setInterval(function(i){var visible_now=d3.select(_this.div).property("offsetWidth")>0;if(visible_now){_this.layout();_this.draw();clearInterval(onVisible)}},500)}else{_this.layout();_this.draw()}};this.events.onInit.call(this);if(this.raw_data.length){this.checkRequired(this.raw_data)}startup(data);return this}function checkRequired(data){var _this=this;var colnames=Object.keys(data[0]);var requiredVars=[];var requiredCols=[];if(this.config.x&&this.config.x.column){requiredVars.push("this.config.x.column");requiredCols.push(this.config.x.column)}if(this.config.y&&this.config.y.column){requiredVars.push("this.config.y.column");requiredCols.push(this.config.y.column)}if(this.config.color_by){requiredVars.push("this.config.color_by");requiredCols.push(this.config.color_by)}if(this.config.marks)this.config.marks.forEach(function(e,i){if(e.per&&e.per.length){e.per.forEach(function(p,j){requiredVars.push("this.config.marks["+i+"].per["+j+"]");requiredCols.push(p)})}if(e.split){requiredVars.push("this.config.marks["+i+"].split");requiredCols.push(e.split)}if(e.values){for(var value in e.values){requiredVars.push("this.config.marks["+i+"].values['"+value+"']");requiredCols.push(value)}}});var missingDataField=false;requiredCols.forEach(function(e,i){if(colnames.indexOf(e)<0){missingDataField=true;d3.select(_this.div).select(".loader").remove();_this.wrap.append("div").style("color","red").html('The value "'+e+'" for the '+requiredVars[i]+"
setting does not match any column in the provided dataset.");throw new Error('Error in settings object: The value "'+e+'" for the '+requiredVars[i]+" setting does not match any column in the provided dataset.")}});return{missingDataField:missingDataField,dataFieldArguments:requiredVars,requiredDataFields:requiredCols}}function layout(){this.svg=this.wrap.append("svg").datum(function(){return null}).attr({class:"wc-svg",xmlns:"http://www.w3.org/2000/svg",version:"1.1",xlink:"http://www.w3.org/1999/xlink"}).append("g").style("display","inline-block");var defs=this.svg.append("defs");defs.append("pattern").attr({id:"diagonal-stripes",x:0,y:0,width:3,height:8,patternUnits:"userSpaceOnUse",patternTransform:"rotate(30)"}).append("rect").attr({x:"0",y:"0",width:"2",height:"8",style:"stroke:none; fill:black"});defs.append("clipPath").attr("id",this.id).append("rect").attr("class","plotting-area");this.svg.append("g").attr("class","y axis").append("text").attr("class","axis-title").attr("transform","rotate(-90)").attr("dy",".75em").attr("text-anchor","middle");this.svg.append("g").attr("class","x axis").append("text").attr("class","axis-title").attr("dy","-.35em").attr("text-anchor","middle");this.svg.append("rect").attr("class","overlay").attr("opacity",0).attr("fill","none").style("pointer-events","all");if(!this.parent)this.wrap.append("ul").datum(function(){return null}).attr("class","legend").style("vertical-align","top").append("span").attr("class","legend-title");d3.select(this.div).select(".loader").remove();this.events.onLayout.call(this)}function draw(raw_data,processed_data){var _this=this;var chart=this;var config=this.config;this.events.onPreprocess.call(this);var raw=raw_data?raw_data:this.raw_data?this.raw_data:[];if(processed_data){console.warn("Drawing the chart using user-defined 'processed_data', this is an experimental, untested feature.")}this.consolidateData(raw);var div_width=parseInt(this.wrap.style("width"));this.setColorScale();var max_width=config.max_width?config.max_width:div_width;this.raw_width=config.x.type==="ordinal"&&+config.x.range_band?(+config.x.range_band+config.x.range_band*config.padding)*this.x_dom.length:config.resizable?max_width:config.width?config.width:div_width;this.raw_height=config.y.type==="ordinal"&&+config.y.range_band?(+config.y.range_band+config.y.range_band*config.padding)*this.y_dom.length:config.resizable?max_width*(1/config.aspect):config.height?config.height:div_width*(1/config.aspect);var pseudo_width=this.svg.select(".overlay").attr("width")?this.svg.select(".overlay").attr("width"):this.raw_width;var pseudo_height=this.svg.select(".overlay").attr("height")?this.svg.select(".overlay").attr("height"):this.raw_height;this.svg.select(".x.axis").select(".axis-title").text(function(d){return typeof config.x.label==="string"?config.x.label:typeof config.x.label==="function"?config.x.label.call(_this):null});this.svg.select(".y.axis").select(".axis-title").text(function(d){return typeof config.y.label==="string"?config.y.label:typeof config.y.label==="function"?config.y.label.call(_this):null});this.xScaleAxis(pseudo_width);this.yScaleAxis(pseudo_height);if(config.resizable&&typeof window!=="undefined"){d3.select(window).on("resize."+this.element+this.id,function(){chart.resize()})}else if(typeof window!=="undefined"){d3.select(window).on("resize."+this.element+this.id,null)}this.events.onDraw.call(this);this.resize()}function naturalSorter(a,b){function chunkify(t){var tz=[];var x=0,y=-1,n=0,i=void 0,j=void 0;while(i=(j=t.charAt(x++)).charCodeAt(0)){var m=i==46||i>=48&&i<=57;if(m!==n){tz[++y]="";n=m}tz[y]+=j}return tz}var aa=chunkify(a.toLowerCase());var bb=chunkify(b.toLowerCase());for(var x=0;aa[x]&&bb[x];x++){if(aa[x]!==bb[x]){var c=Number(aa[x]),d=Number(bb[x]);if(c==aa[x]&&d==bb[x]){return c-d}else{return aa[x]>bb[x]?1:-1}}}return aa.length-bb.length}function setDomain(axis){var _this=this;var otherAxis=axis==="x"?"y":"x";if(this.config[axis].type==="ordinal"){if(this.config[axis].domain){this[axis+"_dom"]=this.config[axis].domain}else if(this.config[axis].order){this[axis+"_dom"]=d3.set(d3.merge(this.marks.map(function(mark){return mark[axis+"_dom"]}))).values().sort(function(a,b){return d3.ascending(_this.config[axis].order.indexOf(a),_this.config[axis].order.indexOf(b))})}else if(this.config[axis].sort&&this.config[axis].sort==="alphabetical-ascending"){this[axis+"_dom"]=d3.set(d3.merge(this.marks.map(function(mark){return mark[axis+"_dom"]}))).values().sort(naturalSorter)}else if(["time","linear"].indexOf(this.config[otherAxis].type)>-1&&this.config[axis].sort==="earliest"){this[axis+"_dom"]=d3.nest().key(function(d){return d[_this.config[axis].column]}).rollup(function(d){return d.map(function(m){return m[_this.config[otherAxis].column]}).filter(function(f){return f instanceof Date})}).entries(this.raw_data).sort(function(a,b){return min(b.values)-min(a.values)}).map(function(m){return m.key})}else if(!this.config[axis].sort||this.config[axis].sort==="alphabetical-descending"){this[axis+"_dom"]=d3.set(d3.merge(this.marks.map(function(mark){return mark[axis+"_dom"]}))).values().sort(naturalSorter).reverse()}else{this[axis+"_dom"]=d3.set(d3.merge(this.marks.map(function(mark){return mark[axis+"_dom"]}))).values()}}else if(this.config.marks.map(function(m){return m["summarize"+otherAxis.toUpperCase()]==="percent"}).indexOf(true)>-1){this[axis+"_dom"]=[0,1]}else{this[axis+"_dom"]=d3.extent(d3.merge(this.marks.map(function(mark){return mark[axis+"_dom"]})))}if(this.config[axis].type==="linear"&&this[axis+"_dom"][0]===this[axis+"_dom"][1])this[axis+"_dom"]=this[axis+"_dom"][0]!==0?[this[axis+"_dom"][0]-this[axis+"_dom"][0]*.01,this[axis+"_dom"][1]+this[axis+"_dom"][1]*.01]:[-1,1];return this[axis+"_dom"]}function consolidateData(raw){var _this=this;this.setDefaults();this.filtered_data=raw;if(this.filters.length){this.filters.forEach(function(filter){_this.filtered_data=_this.filtered_data.filter(function(d){return filter.val==="All"?d:filter.val instanceof Array?filter.val.indexOf(d[filter.col])>-1:d[filter.col]===filter.val})})}this.config.marks.forEach(function(mark,i){if(mark.type!=="bar"){mark.arrange=null;mark.split=null}var mark_info=mark.per?_this.transformData(raw,mark):{data:[],x_dom:[],y_dom:[]};_this.marks[i]={id:mark.id,type:mark.type,per:mark.per,data:mark_info.data,x_dom:mark_info.x_dom,y_dom:mark_info.y_dom,split:mark.split,text:mark.text,arrange:mark.arrange,order:mark.order,summarizeX:mark.summarizeX,summarizeY:mark.summarizeY,tooltip:mark.tooltip,radius:mark.radius,attributes:mark.attributes,values:mark.values}});setDomain.call(this,"x");setDomain.call(this,"y")}function setDefaults(){this.config.x=this.config.x||{};this.config.y=this.config.y||{};this.config.x.label=this.config.x.label!==undefined?this.config.x.label:this.config.x.column;this.config.y.label=this.config.y.label!==undefined?this.config.y.label:this.config.y.column;this.config.x.sort=this.config.x.sort||"alphabetical-ascending";this.config.y.sort=this.config.y.sort||"alphabetical-descending";this.config.x.type=this.config.x.type||"linear";this.config.y.type=this.config.y.type||"linear";this.config.x.range_band=this.config.x.range_band||this.config.range_band;this.config.y.range_band=this.config.y.range_band||this.config.range_band;this.config.margin=this.config.margin||{};this.config.legend=this.config.legend||{};this.config.legend.label=this.config.legend.label!==undefined?this.config.legend.label:this.config.color_by;this.config.legend.location=this.config.legend.location!==undefined?this.config.legend.location:"bottom";this.config.marks=this.config.marks&&this.config.marks.length?this.config.marks:[{}];this.config.marks.forEach(function(m,i){m.id=m.id?m.id:"mark"+(i+1)});this.config.date_format=this.config.date_format||"%x";this.config.padding=this.config.padding!==undefined?this.config.padding:.3;this.config.outer_pad=this.config.outer_pad!==undefined?this.config.outer_pad:.1;this.config.resizable=this.config.resizable!==undefined?this.config.resizable:true;this.config.aspect=this.config.aspect||1.33;this.config.colors=this.config.colors||["rgb(102,194,165)","rgb(252,141,98)","rgb(141,160,203)","rgb(231,138,195)","rgb(166,216,84)","rgb(255,217,47)","rgb(229,196,148)","rgb(179,179,179)"];this.config.scale_text=this.config.scale_text===undefined?true:this.config.scale_text;this.config.transitions=this.config.transitions===undefined?true:this.config.transitions}function cleanData(mark,raw){var _this=this;var dateConvert=d3.time.format(this.config.date_format);var clean=raw;clean=mark.per&&mark.per.length?clean.filter(function(f){return f[mark.per[0]]!==undefined}):clean;if(this.config.x.column){clean=clean.filter(function(f){return[undefined,null].indexOf(f[_this.config.x.column])<0})}if(this.config.y.column){clean=clean.filter(function(f){return[undefined,null].indexOf(f[_this.config.y.column])<0})}if(this.config.x.type==="time"){clean=clean.filter(function(f){return f[_this.config.x.column]instanceof Date?f[_this.config.x.column]:dateConvert.parse(f[_this.config.x.column])});clean.forEach(function(e){return e[_this.config.x.column]=e[_this.config.x.column]instanceof Date?e[_this.config.x.column]:dateConvert.parse(e[_this.config.x.column])})}if(this.config.y.type==="time"){clean=clean.filter(function(f){return f[_this.config.y.column]instanceof Date?f[_this.config.y.column]:dateConvert.parse(f[_this.config.y.column])});clean.forEach(function(e){return e[_this.config.y.column]=e[_this.config.y.column]instanceof Date?e[_this.config.y.column]:dateConvert.parse(e[_this.config.y.column])})}if((this.config.x.type==="linear"||this.config.x.type==="log")&&this.config.x.column){clean=clean.filter(function(f){return mark.summarizeX!=="count"&&mark.summarizeX!=="percent"?!(isNaN(f[_this.config.x.column])||/^\s*$/.test(f[_this.config.x.column])):f})}if((this.config.y.type==="linear"||this.config.y.type==="log")&&this.config.y.column){clean=clean.filter(function(f){return mark.summarizeY!=="count"&&mark.summarizeY!=="percent"?!(isNaN(f[_this.config.y.column])||/^\s*$/.test(f[_this.config.y.column])):f})}return clean}var stats={mean:d3.mean,min:d3.min,max:d3.max,median:d3.median,sum:d3.sum};function summarize(vals){var operation=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"mean";var nvals=vals.filter(function(f){return+f||+f===0}).map(function(m){return+m});if(operation==="cumulative"){return null}var mathed=operation==="count"?vals.length:operation==="percent"?vals.length:stats[operation](nvals);return mathed}function makeNest(mark,entries,sublevel){var _this=this;var dom_xs=[];var dom_ys=[];var this_nest=d3.nest();var totalOrder=void 0;if(this.config.x.type==="linear"&&this.config.x.bin||this.config.y.type==="linear"&&this.config.y.bin){var xy=this.config.x.type==="linear"&&this.config.x.bin?"x":"y";var quant=d3.scale.quantile().domain(d3.extent(entries.map(function(m){return+m[_this.config[xy].column]}))).range(d3.range(+this.config[xy].bin));entries.forEach(function(e){return e.wc_bin=quant(e[_this.config[xy].column])});this_nest.key(function(d){return quant.invertExtent(d.wc_bin)})}else{this_nest.key(function(d){return mark.per.map(function(m){return d[m]}).join(" ")})}if(sublevel){this_nest.key(function(d){return d[sublevel]});this_nest.sortKeys(function(a,b){return _this.config.x.type==="time"?d3.ascending(new Date(a),new Date(b)):_this.config.x.order?d3.ascending(_this.config.x.order.indexOf(a),_this.config.x.order.indexOf(b)):sublevel===_this.config.color_by&&_this.config.legend.order?d3.ascending(_this.config.legend.order.indexOf(a),_this.config.legend.order.indexOf(b)):_this.config.x.type==="ordinal"||_this.config.y.type==="ordinal"?naturalSorter(a,b):d3.ascending(+a,+b)})}this_nest.rollup(function(r){var obj={raw:r};var y_vals=r.map(function(m){return m[_this.config.y.column]}).sort(d3.ascending);var x_vals=r.map(function(m){return m[_this.config.x.column]}).sort(d3.ascending);obj.x=_this.config.x.type==="ordinal"?r[0][_this.config.x.column]:summarize(x_vals,mark.summarizeX);obj.y=_this.config.y.type==="ordinal"?r[0][_this.config.y.column]:summarize(y_vals,mark.summarizeY);obj.x_q25=_this.config.error_bars&&_this.config.y.type==="ordinal"?d3.quantile(x_vals,.25):obj.x;obj.x_q75=_this.config.error_bars&&_this.config.y.type==="ordinal"?d3.quantile(x_vals,.75):obj.x;obj.y_q25=_this.config.error_bars?d3.quantile(y_vals,.25):obj.y;obj.y_q75=_this.config.error_bars?d3.quantile(y_vals,.75):obj.y;dom_xs.push([obj.x_q25,obj.x_q75,obj.x]);dom_ys.push([obj.y_q25,obj.y_q75,obj.y]);if(mark.summarizeY==="cumulative"){var interm=entries.filter(function(f){return _this.config.x.type==="time"?new Date(f[_this.config.x.column])<=new Date(r[0][_this.config.x.column]):+f[_this.config.x.column]<=+r[0][_this.config.x.column]});if(mark.per.length){interm=interm.filter(function(f){return f[mark.per[0]]===r[0][mark.per[0]]})}var cumul=_this.config.x.type==="time"?interm.length:d3.sum(interm.map(function(m){return+m[_this.config.y.column]||+m[_this.config.y.column]===0?+m[_this.config.y.column]:1}));dom_ys.push([cumul]);obj.y=cumul}if(mark.summarizeX==="cumulative"){var _interm=entries.filter(function(f){return _this.config.y.type==="time"?new Date(f[_this.config.y.column])<=new Date(r[0][_this.config.y.column]):+f[_this.config.y.column]<=+r[0][_this.config.y.column]});if(mark.per.length){_interm=_interm.filter(function(f){return f[mark.per[0]]===r[0][mark.per[0]]})}dom_xs.push([_interm.length]);obj.x=_interm.length}return obj});var test=this_nest.entries(entries);var dom_x=d3.extent(d3.merge(dom_xs));var dom_y=d3.extent(d3.merge(dom_ys));if(sublevel&&mark.type==="bar"&&mark.split){test.forEach(function(e){var axis=_this.config.x.type==="ordinal"||_this.config.x.type==="linear"&&_this.config.x.bin?"y":"x";e.total=d3.sum(e.values.map(function(m){return+m.values[axis]}));var counter=0;e.values.forEach(function(v,i){if(_this.config.x.type==="ordinal"||_this.config.x.type==="linear"&&_this.config.x.bin){v.values.y=mark.summarizeY==="percent"?v.values.y/e.total:v.values.y||0;counter+=+v.values.y;v.values.start=e.values[i-1]?counter:v.values.y}else{v.values.x=mark.summarizeX==="percent"?v.values.x/e.total:v.values.x||0;v.values.start=counter;counter+=+v.values.x}})});if(mark.arrange==="stacked"){if(this.config.x.type==="ordinal"||this.config.x.type==="linear"&&this.config.x.bin){dom_y=d3.extent(test.map(function(m){return m.total}))}if(this.config.y.type==="ordinal"||this.config.y.type==="linear"&&this.config.y.bin){dom_x=d3.extent(test.map(function(m){return m.total}))}}}else{var axis=this.config.x.type==="ordinal"||this.config.x.type==="linear"&&this.config.x.bin?"y":"x";test.forEach(function(e){return e.total=e.values[axis]})}if(this.config.x.sort==="total-ascending"&&this.config.x.type=="ordinal"||this.config.y.sort==="total-descending"&&this.config.y.type=="ordinal"){totalOrder=test.sort(function(a,b){return d3.ascending(a.total,b.total)}).map(function(m){return m.key})}else if(this.config.x.sort==="total-descending"&&this.config.x.type=="ordinal"||this.config.y.sort==="total-ascending"&&this.config.y.type=="ordinal"){totalOrder=test.sort(function(a,b){return d3.descending(+a.total,+b.total)}).map(function(m){return m.key})}return{nested:test,dom_x:dom_x,dom_y:dom_y,totalOrder:totalOrder}}function transformData(raw,mark){var _this=this;var config=this.config;var x_behavior=config.x.behavior||"raw";var y_behavior=config.y.behavior||"raw";var sublevel=mark.type==="line"?config.x.column:mark.type==="bar"&&mark.split?mark.split:null;var cleaned=cleanData.call(this,mark,raw);var raw_nest=void 0;if(mark.type==="bar"){raw_nest=mark.arrange!=="stacked"?makeNest.call(this,mark,cleaned,sublevel):makeNest.call(this,mark,cleaned)}else if(mark.summarizeX==="count"||mark.summarizeY==="count"){raw_nest=makeNest.call(this,mark,cleaned)}var raw_dom_x=mark.summarizeX==="cumulative"?[0,cleaned.length]:config.x.type==="ordinal"?d3.set(cleaned.map(function(m){return m[config.x.column]})).values().filter(function(f){return f}):mark.split&&mark.arrange!=="stacked"?d3.extent(d3.merge(raw_nest.nested.map(function(m){return m.values.map(function(p){return p.values.raw.length})}))):mark.summarizeX==="count"?d3.extent(raw_nest.nested.map(function(m){return m.values.raw.length})):d3.extent(cleaned.map(function(m){return+m[config.x.column]}).filter(function(f){return+f||+f===0}));var raw_dom_y=mark.summarizeY==="cumulative"?[0,cleaned.length]:config.y.type==="ordinal"?d3.set(cleaned.map(function(m){return m[config.y.column]})).values().filter(function(f){return f}):mark.split&&mark.arrange!=="stacked"?d3.extent(d3.merge(raw_nest.nested.map(function(m){return m.values.map(function(p){return p.values.raw.length})}))):mark.summarizeY==="count"?d3.extent(raw_nest.nested.map(function(m){return m.values.raw.length})):d3.extent(cleaned.map(function(m){return+m[config.y.column]}).filter(function(f){return+f||+f===0}));var filtered=cleaned;var filt1_xs=[];var filt1_ys=[];if(this.filters.length){this.filters.forEach(function(e){filtered=filtered.filter(function(d){return e.val==="All"?d:e.val instanceof Array?e.val.indexOf(d[e.col])>-1:d[e.col]===e.val})});if(config.x.behavior==="firstfilter"||config.y.behavior==="firstfilter"){this.filters[0].choices.filter(function(f){return f!=="All"}).forEach(function(e){var perfilter=cleaned.filter(function(f){return f[_this.filters[0].col]===e});var filt_nested=makeNest.call(_this,mark,perfilter,sublevel);filt1_xs.push(filt_nested.dom_x);filt1_ys.push(filt_nested.dom_y)})}}if(mark.values){var _loop=function _loop(a){filtered=filtered.filter(function(f){return mark.values[a].indexOf(f[a])>-1})};for(var a in mark.values){_loop(a)}}var filt1_dom_x=d3.extent(d3.merge(filt1_xs));var filt1_dom_y=d3.extent(d3.merge(filt1_ys));var current_nested=makeNest.call(this,mark,filtered,sublevel);var flex_dom_x=current_nested.dom_x;var flex_dom_y=current_nested.dom_y;if(mark.type==="bar"){if(config.y.type==="ordinal"&&mark.summarizeX==="count"){config.x.domain=config.x.domain?[0,config.x.domain[1]]:[0,null]}else if(config.x.type==="ordinal"&&mark.summarizeY==="count"){config.y.domain=config.y.domain?[0,config.y.domain[1]]:[0,null]}}var nonall=Boolean(this.filters.length&&this.filters[0].val!=="All"&&this.filters.slice(1).filter(function(f){return f.val==="All"}).length===this.filters.length-1);var pre_x_dom=!this.filters.length?flex_dom_x:x_behavior==="raw"?raw_dom_x:nonall&&x_behavior==="firstfilter"?filt1_dom_x:flex_dom_x;var pre_y_dom=!this.filters.length?flex_dom_y:y_behavior==="raw"?raw_dom_y:nonall&&y_behavior==="firstfilter"?filt1_dom_y:flex_dom_y;var x_dom=config.x_dom?config.x_dom:config.x.type==="ordinal"&&config.x.behavior==="flex"?d3.set(filtered.map(function(m){return m[config.x.column]})).values():config.x.type==="ordinal"?d3.set(cleaned.map(function(m){return m[config.x.column]})).values():pre_x_dom;var y_dom=config.y_dom?config.y_dom:config.y.type==="ordinal"&&config.y.behavior==="flex"?d3.set(filtered.map(function(m){return m[config.y.column]})).values():config.y.type==="ordinal"?d3.set(cleaned.map(function(m){return m[config.y.column]})).values():pre_y_dom;if(mark.type==="bar"){if(config.x.behavior!=="flex"&&config.x.type==="linear"&&config.y.type==="ordinal"&&raw_dom_x[0]>=0)x_dom[0]=0;if(config.y.behavior!=="flex"&&config.x.type==="ordinal"&&config.y.type==="linear"&&raw_dom_y[0]>=0)y_dom[0]=0}if(config.x.domain&&(config.x.domain[0]||config.x.domain[0]===0)){x_dom[0]=config.x.domain[0]}if(config.x.domain&&(config.x.domain[1]||config.x.domain[1]===0)){x_dom[1]=config.x.domain[1]}if(config.y.domain&&(config.y.domain[0]||config.y.domain[0]===0)){y_dom[0]=config.y.domain[0]}if(config.y.domain&&(config.y.domain[1]||config.y.domain[1]===0)){y_dom[1]=config.y.domain[1]}if(config.x.type==="ordinal"&&!config.x.order){config.x.order=current_nested.totalOrder}if(config.y.type==="ordinal"&&!config.y.order){config.y.order=current_nested.totalOrder}this.current_data=current_nested.nested;this.events.onDatatransform.call(this);return{config:mark,data:current_nested.nested,x_dom:x_dom,y_dom:y_dom}}function setColorScale(){var config=this.config;var data=config.legend.behavior==="flex"?this.filtered_data:this.raw_data;var colordom=Array.isArray(config.color_dom)&&config.color_dom.length?config.color_dom.slice():d3.set(data.map(function(m){return m[config.color_by]})).values().filter(function(f){return f&&f!=="undefined"});if(config.legend.order)colordom.sort(function(a,b){return d3.ascending(config.legend.order.indexOf(a),config.legend.order.indexOf(b))});else colordom.sort(naturalSorter);this.colorScale=d3.scale.ordinal().domain(colordom).range(config.colors)}function xScaleAxis(max_range,domain,type){if(max_range===undefined){max_range=this.plot_width}if(domain===undefined){domain=this.x_dom}if(type===undefined){type=this.config.x.type}var config=this.config;var x=void 0;if(type==="log"){x=d3.scale.log()}else if(type==="ordinal"){x=d3.scale.ordinal()}else if(type==="time"){x=d3.time.scale()}else{x=d3.scale.linear()}x.domain(domain);if(type==="ordinal"){x.rangeBands([0,+max_range],config.padding,config.outer_pad)}else{x.range([0,+max_range]).clamp(Boolean(config.x.clamp))}var xFormat=config.x.format?config.x.format:config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?"0%":type==="time"?"%x":".0f";var tick_count=Math.max(2,Math.min(max_range/80,8));var xAxis=d3.svg.axis().scale(x).orient(config.x.location).ticks(tick_count).tickFormat(type==="ordinal"?null:type==="time"?d3.time.format(xFormat):d3.format(xFormat)).tickValues(config.x.ticks?config.x.ticks:null).innerTickSize(6).outerTickSize(3);this.svg.select("g.x.axis").attr("class","x axis "+type);this.x=x;this.xAxis=xAxis}function yScaleAxis(max_range,domain,type){if(max_range===undefined){max_range=this.plot_height}if(domain===undefined){domain=this.y_dom}if(type===undefined){type=this.config.y.type}var config=this.config;var y=void 0;if(type==="log"){y=d3.scale.log()}else if(type==="ordinal"){y=d3.scale.ordinal()}else if(type==="time"){y=d3.time.scale()}else{y=d3.scale.linear()}y.domain(domain);if(type==="ordinal"){y.rangeBands([+max_range,0],config.padding,config.outer_pad)}else{y.range([+max_range,0]).clamp(Boolean(config.y_clamp))}var yFormat=config.y.format?config.y.format:config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?"0%":".0f";var tick_count=Math.max(2,Math.min(max_range/80,8));var yAxis=d3.svg.axis().scale(y).orient("left").ticks(tick_count).tickFormat(type==="ordinal"?null:type==="time"?d3.time.format(yFormat):d3.format(yFormat)).tickValues(config.y.ticks?config.y.ticks:null).innerTickSize(6).outerTickSize(3);this.svg.select("g.y.axis").attr("class","y axis "+type);this.y=y;this.yAxis=yAxis}function resize(){var config=this.config;var aspect2=1/config.aspect;var div_width=parseInt(this.wrap.style("width"));var max_width=config.max_width?config.max_width:div_width;var preWidth=!config.resizable?config.width:!max_width||div_width=600){font_size="14px";point_size=4;stroke_width=2}else if(width>450&&width<600){font_size="12px";point_size=3;stroke_width=2}else if(width>300&&width<450){font_size="10px";point_size=2;stroke_width=2}else if(width<=300){font_size="10px";point_size=2;stroke_width=1}this.wrap.style("font-size",font_size);this.config.flex_point_size=point_size;this.config.flex_stroke_width=stroke_width}function setMargins(){var _this=this;var y_ticks=this.yAxis.tickFormat()?this.y.domain().map(function(m){return _this.yAxis.tickFormat()(m)}):this.y.domain();var max_y_text_length=d3.max(y_ticks.map(function(m){return String(m).length}));if(this.config.y_format&&this.config.y_format.indexOf("%")>-1){max_y_text_length+=1}max_y_text_length=Math.max(2,max_y_text_length);var x_label_on=this.config.x.label?1.5:0;var y_label_on=this.config.y.label?1.5:.25;var font_size=parseInt(this.wrap.style("font-size"));var x_second=this.config.x2_interval?1:0;var y_margin=max_y_text_length*font_size*.5+font_size*y_label_on*1.5||8;var x_margin=font_size+font_size/1.5+font_size*x_label_on+font_size*x_second||8;y_margin+=6;x_margin+=3;return{top:this.config.margin&&this.config.margin.top?this.config.margin.top:8,right:this.config.margin&&this.config.margin.right?this.config.margin.right:16,bottom:this.config.margin&&this.config.margin.bottom?this.config.margin.bottom:x_margin,left:this.config.margin&&this.config.margin.left?this.config.margin.left:y_margin}}function drawGridLines(){this.wrap.classed("gridlines",this.config.gridlines);if(this.config.gridlines){this.svg.select(".y.axis").selectAll(".tick line").attr("x1",0);this.svg.select(".x.axis").selectAll(".tick line").attr("y1",0);if(this.config.gridlines==="y"||this.config.gridlines==="xy")this.svg.select(".y.axis").selectAll(".tick line").attr("x1",this.plot_width);if(this.config.gridlines==="x"||this.config.gridlines==="xy")this.svg.select(".x.axis").selectAll(".tick line").attr("y1",-this.plot_height)}else{this.svg.select(".y.axis").selectAll(".tick line").attr("x1",0);this.svg.select(".x.axis").selectAll(".tick line").attr("y1",0)}}function makeLegend(){var scale$$1=arguments.length>0&&arguments[0]!==undefined?arguments[0]:this.colorScale;var label=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var custom_data=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var config=this.config;config.legend.mark=config.legend.mark?config.legend.mark:config.marks.length&&config.marks[0].type==="bar"?"square":config.marks.length?config.marks[0].type:"square";var legend_label=label?label:typeof config.legend.label==="string"?config.legend.label:"";var legendOriginal=this.legend||this.wrap.select(".legend");var legend=legendOriginal;if(!this.parent){if(this.config.legend.location==="top"||this.config.legend.location==="left"){this.wrap.node().insertBefore(legendOriginal.node(),this.svg.node().parentNode)}else{this.wrap.node().appendChild(legendOriginal.node())}}else{if(this.config.legend.location==="top"||this.config.legend.location==="left"){this.parent.wrap.node().insertBefore(legendOriginal.node(),this.parent.wrap.select(".wc-chart").node())}else{this.parent.wrap.node().appendChild(legendOriginal.node())}}legend.style("padding",0);var legend_data=custom_data||scale$$1.domain().slice(0).filter(function(f){return f!==undefined&&f!==null}).map(function(m){return{label:m,mark:config.legend.mark}});legend.select(".legend-title").text(legend_label).style("display",legend_label?"inline":"none").style("margin-right","1em");var leg_parts=legend.selectAll(".legend-item").data(legend_data,function(d){return d.label+d.mark});leg_parts.exit().remove();var legendPartDisplay=this.config.legend.location==="bottom"||this.config.legend.location==="top"?"inline-block":"block";var new_parts=leg_parts.enter().append("li").attr("class","legend-item").style({"list-style-type":"none","margin-right":"1em"});new_parts.append("span").attr("class","legend-mark-text").style("color",function(d){return scale$$1(d.label)})
-;new_parts.append("svg").attr("class","legend-color-block").attr("width","1.1em").attr("height","1.1em").style({position:"relative",top:"0.2em"});leg_parts.style("display",legendPartDisplay);if(config.legend.order){leg_parts.sort(function(a,b){return d3.ascending(config.legend.order.indexOf(a.label),config.legend.order.indexOf(b.label))})}leg_parts.selectAll(".legend-color-block").select(".legend-mark").remove();leg_parts.selectAll(".legend-color-block").each(function(e){var svg$$1=d3.select(this);if(e.mark==="circle"){svg$$1.append("circle").attr({cx:".5em",cy:".5em",r:".45em",class:"legend-mark"})}else if(e.mark==="line"){svg$$1.append("line").attr({x1:0,y1:".5em",x2:"1em",y2:".5em","stroke-width":2,"shape-rendering":"crispEdges",class:"legend-mark"})}else if(e.mark==="square"){svg$$1.append("rect").attr({height:"1em",width:"1em",class:"legend-mark","shape-rendering":"crispEdges"})}});leg_parts.selectAll(".legend-color-block").select(".legend-mark").attr("fill",function(d){return d.color||scale$$1(d.label)}).attr("stroke",function(d){return d.color||scale$$1(d.label)}).each(function(e){d3.select(this).attr(e.attributes)});new_parts.append("span").attr("class","legend-label").style("margin-left","0.25em").text(function(d){return d.label});if(scale$$1.domain().length>0){var legendDisplay=this.config.legend.location==="bottom"||this.config.legend.location==="top"?"block":"inline-block";legend.style("display",legendDisplay)}else{legend.style("display","none")}this.legend=legend}function updateDataMarks(){this.drawBars(this.marks.filter(function(f){return f.type==="bar"}));this.drawLines(this.marks.filter(function(f){return f.type==="line"}));this.drawPoints(this.marks.filter(function(f){return f.type==="circle"}));this.drawText(this.marks.filter(function(f){return f.type==="text"}));this.marks.supergroups=this.svg.selectAll("g.supergroup")}function drawArea(area_drawer,area_data,datum_accessor){var class_match=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"chart-area";var _this=this;var bind_accessor=arguments[4];var attr_accessor=arguments.length>5&&arguments[5]!==undefined?arguments[5]:function(d){return d};var area_grps=this.svg.selectAll("."+class_match).data(area_data,bind_accessor);area_grps.exit().remove();area_grps.enter().append("g").attr("class",function(d){return class_match+" "+d.key}).append("path");var areaPaths=area_grps.select("path").datum(datum_accessor).attr("fill",function(d){var d_attr=attr_accessor(d);return d_attr?_this.colorScale(d_attr[_this.config.color_by]):null}).attr("fill-opacity",this.config.fill_opacity||this.config.fill_opacity===0?this.config.fill_opacity:.3);var areaPathTransitions=this.config.transitions?areaPaths.transition():areaPaths;areaPathTransitions.attr("d",area_drawer);return area_grps}function drawBars(marks){var _this=this;var rawData=this.raw_data;var config=this.config;var bar_supergroups=this.svg.selectAll(".bar-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});bar_supergroups.enter().append("g").attr("class",function(d){return"supergroup bar-supergroup "+d.id});bar_supergroups.exit().remove();var bar_groups=bar_supergroups.selectAll(".bar-group").data(function(d){return d.data},function(d){return d.key});var old_bar_groups=bar_groups.exit();var nu_bar_groups=void 0;var bars=void 0;var oldBarsTrans=config.transitions?old_bar_groups.selectAll(".bar").transition():old_bar_groups.selectAll(".bar");var oldBarGroupsTrans=config.transitions?old_bar_groups.transition():old_bar_groups;if(config.x.type==="ordinal"){oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values.sort(function(a,b){return _this.colorScale.domain().indexOf(b.key)-_this.colorScale.domain().indexOf(a.key)}):[d]},function(d){return d.key});var exitBars=config.transitions?bars.exit().transition():bars.exit();exitBars.attr("y",this.y(0)).attr("height",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("y",this.y(0)).attr("height",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.tooltip=mark.tooltip;d.arrange=mark.split&&mark.arrange?mark.arrange:mark.split?"grouped":null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d3.select(this).attr(mark.attributes)});var xformat=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var yformat=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,xformat(d.values.x)).replace(/\$y/g,yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var barsTrans=config.transitions?bars.transition():bars;barsTrans.attr("x",function(d){var position=void 0;if(!d.arrange||d.arrange==="stacked"){return _this.x(d.values.x)}else if(d.arrange==="nested"){var _position=d.subcats.indexOf(d.key);var offset=_position?_this.x.rangeBand()/(d.subcats.length*.75)/_position:_this.x.rangeBand();return _this.x(d.values.x)+(_this.x.rangeBand()-offset)/2}else{position=d.subcats.indexOf(d.key);return _this.x(d.values.x)+_this.x.rangeBand()/d.subcats.length*position}}).attr("y",function(d){if(d.arrange!=="stacked"){return _this.y(d.values.y)}else{return _this.y(d.values.start)}}).attr("width",function(d){if(!d.arrange||d.arrange==="stacked"){return _this.x.rangeBand()}else if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);return position?_this.x.rangeBand()/(d.subcats.length*.75)/position:_this.x.rangeBand()}else{return _this.x.rangeBand()/d.subcats.length}}).attr("height",function(d){return _this.y(0)-_this.y(d.values.y)})}else if(config.y.type==="ordinal"){oldBarsTrans.attr("x",this.x(0)).attr("width",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values.sort(function(a,b){return _this.colorScale.domain().indexOf(b.key)-_this.colorScale.domain().indexOf(a.key)}):[d]},function(d){return d.key});var _exitBars=config.transitions?bars.exit().transition():bars.exit();_exitBars.attr("x",this.x(0)).attr("width",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("x",this.x(0)).attr("width",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split&&mark.arrange?mark.arrange:mark.split?"grouped":null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d.tooltip=mark.tooltip;d3.select(this).attr(mark.attributes)});var _xformat=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat(d.values.x)).replace(/\$y/g,_yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans=config.transitions?bars.transition():bars;_barsTrans.attr("x",function(d){if(d.arrange==="stacked"||!d.arrange){return d.values.start!==undefined?_this.x(d.values.start):_this.x(0)}else{return _this.x(0)}}).attr("y",function(d){if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);var offset=position?_this.y.rangeBand()/(d.subcats.length*.75)/position:_this.y.rangeBand();return _this.y(d.values.y)+(_this.y.rangeBand()-offset)/2}else if(d.arrange==="grouped"){var _position2=d.subcats.indexOf(d.key);return _this.y(d.values.y)+_this.y.rangeBand()/d.subcats.length*_position2}else{return _this.y(d.values.y)}}).attr("width",function(d){return _this.x(d.values.x)-_this.x(0)}).attr("height",function(d){if(config.y.type==="quantile"){return 20}else if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);return position?_this.y.rangeBand()/(d.subcats.length*.75)/position:_this.y.rangeBand()}else if(d.arrange==="grouped"){return _this.y.rangeBand()/d.subcats.length}else{return _this.y.rangeBand()}})}else if(["linear","log"].indexOf(config.x.type)>-1&&config.x.bin){oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values:[d]},function(d){return d.key});var _exitBars2=config.transitions?bars.exit().transition():bars.exit();_exitBars2.attr("y",this.y(0)).attr("height",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("y",this.y(0)).attr("height",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split?mark.arrange:null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d3.select(this).attr(mark.attributes);var parent=d3.select(this.parentNode).datum();var rangeSet=parent.key.split(",").map(function(m){return+m});d.rangeLow=d3.min(rangeSet);d.rangeHigh=d3.max(rangeSet);d.tooltip=mark.tooltip});var _xformat2=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat2=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat2(d.values.x)).replace(/\$y/g,_yformat2(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans2=config.transitions?bars.transition():bars;_barsTrans2.attr("x",function(d){return _this.x(d.rangeLow)}).attr("y",function(d){if(d.arrange!=="stacked"){return _this.y(d.values.y)}else{return _this.y(d.values.start)}}).attr("width",function(d){return _this.x(d.rangeHigh)-_this.x(d.rangeLow)}).attr("height",function(d){return _this.y(0)-_this.y(d.values.y)})}else if(["linear","log"].indexOf(config.y.type)>-1&&config.y.type==="linear"&&config.y.bin){oldBarsTrans.attr("x",this.x(0)).attr("width",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values:[d]},function(d){return d.key});var _exitBars3=config.transitions?bars.exit().transition():bars.exit();_exitBars3.attr("x",this.x(0)).attr("width",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("x",this.x(0)).attr("width",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split?mark.arrange:null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();var parent=d3.select(this.parentNode).datum();var rangeSet=parent.key.split(",").map(function(m){return+m});d.rangeLow=d3.min(rangeSet);d.rangeHigh=d3.max(rangeSet);d.tooltip=mark.tooltip});var _xformat3=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat3=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat3(d.values.x)).replace(/\$y/g,_yformat3(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans3=config.transitions?bars.transition():bars;_barsTrans3.attr("x",function(d){if(d.arrange==="stacked"){return _this.x(d.values.start)}else{return _this.x(0)}}).attr("y",function(d){return _this.y(d.rangeHigh)}).attr("width",function(d){return _this.x(d.values.x)}).attr("height",function(d){return _this.y(d.rangeLow)-_this.y(d.rangeHigh)})}else{oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();bar_supergroups.remove()}bar_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll(".bar-group")})}function drawLines(marks){var _this=this;var config=this.config;var line=d3.svg.line().interpolate(config.interpolate).x(function(d){return config.x.type==="linear"||config.x.type=="log"?_this.x(+d.values.x):config.x.type==="time"?_this.x(new Date(d.values.x)):_this.x(d.values.x)+_this.x.rangeBand()/2}).y(function(d){return config.y.type==="linear"||config.y.type=="log"?_this.y(+d.values.y):config.y.type==="time"?_this.y(new Date(d.values.y)):_this.y(d.values.y)+_this.y.rangeBand()/2});var line_supergroups=this.svg.selectAll(".line-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});line_supergroups.enter().append("g").attr("class",function(d){return"supergroup line-supergroup "+d.id});line_supergroups.exit().remove();var line_grps=line_supergroups.selectAll(".line").data(function(d){return d.data},function(d){return d.key});line_grps.exit().remove();var nu_line_grps=line_grps.enter().append("g").attr("class",function(d){return d.key+" line"});nu_line_grps.append("path");nu_line_grps.append("title");var linePaths=line_grps.select("path").attr("class","wc-data-mark").datum(function(d){return d.values}).attr("stroke",function(d){return _this.colorScale(d[0].values.raw[0][config.color_by])}).attr("stroke-width",config.stroke_width?config.stroke_width:config.flex_stroke_width).attr("stroke-linecap","round").attr("fill","none");var linePathsTrans=config.transitions?linePaths.transition():linePaths;linePathsTrans.attr("d",line);line_grps.each(function(d){var mark=d3.select(this.parentNode).datum();d.tooltip=mark.tooltip;d3.select(this).select("path").attr(mark.attributes)});line_grps.select("title").text(function(d){var tt=d.tooltip||"";var xformat=config.x.summary==="percent"?d3.format("0%"):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):d3.format(config.y.format);return tt.replace(/\$x/g,xformat(d.values.x)).replace(/\$y/g,yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values[0].values.raw[0][orig]})});line_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.line");d.paths=d.groups.select("path")});return line_grps}function drawPoints(marks){var _this=this;var config=this.config;var point_supergroups=this.svg.selectAll(".point-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});point_supergroups.enter().append("g").attr("class",function(d){return"supergroup point-supergroup "+d.id});point_supergroups.exit().remove();var points=point_supergroups.selectAll(".point").data(function(d){return d.data},function(d){return d.key});var oldPoints=points.exit();var oldPointsTrans=config.transitions?oldPoints.selectAll("circle").transition():oldPoints.selectAll("circle");oldPointsTrans.attr("r",0);var oldPointGroupTrans=config.transitions?oldPoints.transition():oldPoints;oldPointGroupTrans.remove();var nupoints=points.enter().append("g").attr("class",function(d){return d.key+" point"});nupoints.append("circle").attr("class","wc-data-mark").attr("r",0);nupoints.append("title");points.select("circle").attr("fill-opacity",config.fill_opacity||config.fill_opacity===0?config.fill_opacity:.6).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});points.each(function(d){var mark=d3.select(this.parentNode).datum();d.mark=mark;d3.select(this).select("circle").attr(mark.attributes)});var pointsTrans=config.transitions?points.select("circle").transition():points.select("circle");pointsTrans.attr("r",function(d){return d.mark.radius||config.flex_point_size}).attr("cx",function(d){var x_pos=_this.x(d.values.x)||0;return config.x.type==="ordinal"?x_pos+_this.x.rangeBand()/2:x_pos}).attr("cy",function(d){var y_pos=_this.y(d.values.y)||0;return config.y.type==="ordinal"?y_pos+_this.y.rangeBand()/2:y_pos});points.select("title").text(function(d){var tt=d.mark.tooltip||"";var xformat=config.x.summary==="percent"?d3.format("0%"):config.x.type==="time"?d3.time.format(config.x.format):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):config.y.type==="time"?d3.time.format(config.y.format):d3.format(config.y.format);return tt.replace(/\$x/g,config.x.type==="time"?xformat(new Date(d.values.x)):xformat(d.values.x)).replace(/\$y/g,config.y.type==="time"?yformat(new Date(d.values.y)):yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});point_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.point");d.circles=d.groups.select("circle")});return points}function drawText(marks){var _this=this;var config=this.config;var textSupergroups=this.svg.selectAll(".text-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});textSupergroups.enter().append("g").attr("class",function(d){return"supergroup text-supergroup "+d.id});textSupergroups.exit().remove();var texts=textSupergroups.selectAll(".text").data(function(d){return d.data},function(d){return d.key});var oldTexts=texts.exit();var oldTextGroupTrans=config.transitions?oldTexts.transition():oldTexts;oldTextGroupTrans.remove();var nutexts=texts.enter().append("g").attr("class",function(d){return d.key+" text"});nutexts.append("text").attr("class","wc-data-mark");function attachMarks(d){d.mark=d3.select(this.parentNode).datum();d3.select(this).select("text").attr(d.mark.attributes)}texts.each(attachMarks);texts.select("text").text(function(d){var tt=d.mark.text||"";var xformat=config.x.summary==="percent"?d3.format("0%"):config.x.type==="time"?d3.time.format(config.x.format):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):config.y.type==="time"?d3.time.format(config.y.format):d3.format(config.y.format);return tt.replace(/\$x/g,config.x.type==="time"?xformat(new Date(d.values.x)):xformat(d.values.x)).replace(/\$y/g,config.y.type==="time"?yformat(new Date(d.values.y)):yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var textsTrans=config.transitions?texts.select("text").transition():texts.select("text");textsTrans.attr("x",function(d){var xPos=_this.x(d.values.x)||0;return config.x.type==="ordinal"?xPos+_this.x.rangeBand()/2:xPos}).attr("y",function(d){var yPos=_this.y(d.values.y)||0;return config.y.type==="ordinal"?yPos+_this.y.rangeBand()/2:yPos});textSupergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.text");d.texts=d.groups.select("text")});return texts}function destroy(){var destroyControls=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;this.events.onDestroy.call(this);var context=this;d3.select(window).on("resize."+context.element+context.id,null);if(destroyControls&&this.controls){this.controls.destroy()}this.wrap.remove()}var chartProto={raw_data:[],config:{}};var chart=Object.create(chartProto,{checkRequired:{value:checkRequired},consolidateData:{value:consolidateData},draw:{value:draw},destroy:{value:destroy},drawArea:{value:drawArea},drawBars:{value:drawBars},drawGridlines:{value:drawGridLines},drawLines:{value:drawLines},drawPoints:{value:drawPoints},drawText:{value:drawText},init:{value:init},layout:{value:layout},makeLegend:{value:makeLegend},resize:{value:resize},setColorScale:{value:setColorScale},setDefaults:{value:setDefaults},setMargins:{value:setMargins},textSize:{value:textSize},transformData:{value:transformData},updateDataMarks:{value:updateDataMarks},xScaleAxis:{value:xScaleAxis},yScaleAxis:{value:yScaleAxis}});var chartCount=0;function createChart(){var element=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var controls=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var thisChart=Object.create(chart);thisChart.div=element;thisChart.config=Object.create(config);thisChart.controls=controls;thisChart.raw_data=[];thisChart.filters=[];thisChart.marks=[];thisChart.wrap=d3.select(thisChart.div).append("div").datum(thisChart);thisChart.events={onInit:function onInit(){},onLayout:function onLayout(){},onPreprocess:function onPreprocess(){},onDatatransform:function onDatatransform(){},onDraw:function onDraw(){},onResize:function onResize(){},onDestroy:function onDestroy(){}};thisChart.on=function(event,callback){var possible_events=["init","layout","preprocess","datatransform","draw","resize","destroy"];if(possible_events.indexOf(event)<0){return}if(callback){thisChart.events["on"+event.charAt(0).toUpperCase()+event.slice(1)]=callback}};chartCount++;thisChart.id=chartCount;return thisChart}function changeOption(option,value,callback){var _this=this;this.targets.forEach(function(e){if(option instanceof Array){option.forEach(function(o){return _this.stringAccessor(e.config,o,value)})}else{_this.stringAccessor(e.config,option,value)}if(callback){callback()}e.draw()})}function checkRequired$1(dataset){if(!dataset[0]||!this.config.inputs){return}var colnames=d3.keys(dataset[0]);this.config.inputs.forEach(function(e,i){if(e.type==="subsetter"&&colnames.indexOf(e.value_col)===-1){throw new Error('Error in settings object: the value "'+e.value_col+'" does not match any column in the provided dataset.')}})}function controlUpdate(){var _this=this;if(this.config.inputs&&this.config.inputs.length&&this.config.inputs[0]){this.config.inputs.forEach(function(e){return _this.makeControlItem(e)})}}function destroy$1(){this.wrap.remove()}function init$1(data){this.data=data;if(!this.config.builder){this.checkRequired(this.data)}this.layout()}function layout$1(){this.wrap.selectAll("*").remove();this.ready=true;this.controlUpdate()}function makeControlItem(control){var control_wrap=this.wrap.append("div").attr("class","control-group").classed("inline",control.inline).datum(control);var ctrl_label=control_wrap.append("span").attr("class","wc-control-label").text(control.label);if(control.required){ctrl_label.append("span").attr("class","label label-required").text("Required")}control_wrap.append("span").attr("class","span-description").text(control.description);if(control.type==="text"){this.makeTextControl(control,control_wrap)}else if(control.type==="number"){this.makeNumberControl(control,control_wrap)}else if(control.type==="list"){this.makeListControl(control,control_wrap)}else if(control.type==="dropdown"){this.makeDropdownControl(control,control_wrap)}else if(control.type==="btngroup"){this.makeBtnGroupControl(control,control_wrap)}else if(control.type==="checkbox"){this.makeCheckboxControl(control,control_wrap)}else if(control.type==="radio"){this.makeRadioControl(control,control_wrap)}else if(control.type==="subsetter"){this.makeSubsetterControl(control,control_wrap)}else{throw new Error('Each control must have a type! Choose from: "text", "number", "list", "dropdown", "btngroup", "checkbox", "radio", "subsetter"')}}function makeBtnGroupControl(control,control_wrap){var _this=this;var option_data=control.values?control.values:d3.keys(this.data[0]);var btn_wrap=control_wrap.append("div").attr("class","btn-group");var changers=btn_wrap.selectAll("button").data(option_data).enter().append("button").attr("class","btn btn-default btn-sm").text(function(d){return d}).classed("btn-primary",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)===d});changers.on("click",function(d){changers.each(function(e){d3.select(this).classed("btn-primary",e===d)});_this.changeOption(control.option,d,control.callback)})}function makeCheckboxControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","checkbox").attr("class","changer").datum(control).property("checked",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("checked");_this.changeOption(d.option,value,control.callback)})}function makeDropdownControl(control,control_wrap){var _this=this;var mainOption=control.option||control.options[0];var changer=control_wrap.append("select").attr("class","changer").attr("multiple",control.multiple?true:null).datum(control);var opt_values=control.values&&control.values instanceof Array?control.values:control.values?d3.set(this.data.map(function(m){return m[_this.targets[0].config[control.values]]})).values():d3.keys(this.data[0]);if(!control.require||control.none){opt_values.unshift("None")}var options=changer.selectAll("option").data(opt_values).enter().append("option").text(function(d){return d}).property("selected",function(d){return _this.stringAccessor(_this.targets[0].config,mainOption)===d});changer.on("change",function(d){var value=changer.property("value")==="None"?null:changer.property("value");if(control.multiple){value=options.filter(function(f){return d3.select(this).property("selected")})[0].map(function(m){return d3.select(m).property("value")}).filter(function(f){return f!=="None"})}if(control.options){_this.changeOption(control.options,value,control.callback)}else{_this.changeOption(control.option,value,control.callback)}});return changer}function makeListControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","text").attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("value")?changer.property("value").split(",").map(function(m){return m.trim()}):null;_this.changeOption(control.option,value,control.callback)})}function makeNumberControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","number").attr("min",control.min!==undefined?control.min:0).attr("max",control.max).attr("step",control.step||1).attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=+changer.property("value");_this.changeOption(control.option,value,control.callback)})}function makeRadioControl(control,control_wrap){var _this=this;var changers=control_wrap.selectAll("label").data(control.values||d3.keys(this.data[0])).enter().append("label").attr("class","radio").text(function(d,i){return control.relabels?control.relabels[i]:d}).append("input").attr("type","radio").attr("class","changer").attr("name",control.option.replace(".","-")+"-"+this.targets[0].id).property("value",function(d){return d}).property("checked",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)===d});changers.on("change",function(d){var value=null;changers.each(function(c){if(d3.select(this).property("checked")){value=d3.select(this).property("value")==="none"?null:c}});_this.changeOption(control.option,value,control.callback)})}function makeSubsetterControl(control,control_wrap){var targets=this.targets;var changer=control_wrap.append("select").attr("class","changer").attr("multiple",control.multiple?true:null).datum(control);var option_data=control.values?control.values:d3.set(this.data.map(function(m){return m[control.value_col]}).filter(function(f){return f})).values();option_data.sort(naturalSorter);control.start=control.start?control.start:control.loose?option_data[0]:null;if(!control.multiple&&!control.start){option_data.unshift("All")}control.loose=!control.loose&&control.start?true:control.loose;var options=changer.selectAll("option").data(option_data).enter().append("option").text(function(d){return d}).property("selected",function(d){return d===control.start});targets.forEach(function(e){var match=e.filters.slice().map(function(m){return m.col===control.value_col}).indexOf(true);if(match>-1){e.filters[match]={col:control.value_col,val:control.start?control.start:"All",choices:option_data,loose:control.loose}}else{e.filters.push({col:control.value_col,val:control.start?control.start:"All",choices:option_data,loose:control.loose})}});function setSubsetter(target,obj){var match=-1;target.filters.forEach(function(e,i){if(e.col===obj.col){match=i}});if(match>-1){target.filters[match]=obj}}changer.on("change",function(d){if(control.multiple){var values=options.filter(function(f){return d3.select(this).property("selected")})[0].map(function(m){return d3.select(m).property("text")});var new_filter={col:control.value_col,val:values,choices:option_data,loose:control.loose};targets.forEach(function(e){setSubsetter(e,new_filter);if(control.callback){control.callback()}e.draw()})}else{var value=d3.select(this).select("option:checked").property("text");var _new_filter={col:control.value_col,val:value,choices:option_data,loose:control.loose};targets.forEach(function(e){setSubsetter(e,_new_filter);if(control.callback){control.callback()}e.draw()})}})}function makeTextControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","text").attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("value");_this.changeOption(control.option,value,control.callback)})}function stringAccessor(o,s,v){s=s.replace(/\[(\w+)\]/g,".$1");s=s.replace(/^\./,"");var a=s.split(".");for(var i=0,n=a.length;i0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var thisControls=Object.create(controls);thisControls.div=element;thisControls.config=Object.create(config);thisControls.config.inputs=thisControls.config.inputs||[];thisControls.targets=[];if(config.location==="bottom"){thisControls.wrap=d3.select(element).append("div").attr("class","wc-controls")}else{thisControls.wrap=d3.select(element).insert("div",":first-child").attr("class","wc-controls")}thisControls.wrap.datum(thisControls);return thisControls}var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};function clone(obj){var copy=void 0;if("object"!=(typeof obj==="undefined"?"undefined":_typeof(obj))||null==obj)return obj;if(obj instanceof Date){copy=new Date;copy.setTime(obj.getTime());return copy}if(obj instanceof Array){copy=[];for(var i=0,len=obj.length;i-1:filter.val===d[filter.col]});return match}):clone(this.data.raw)}function updateDataObject(){this.data.raw=this.data.passed;this.data.filtered=this.data.passed;this.config.activePage=0;this.config.startIndex=this.config.activePage*this.config.nRowsPerPage;this.config.endIndex=this.config.startIndex+this.config.nRowsPerPage}function applySearchTerm(data){var _this=this;if(this.searchable.searchTerm){this.data.searched=this.data.filtered.filter(function(d){var match=false;Object.keys(d).filter(function(key){return _this.config.cols.indexOf(key)>-1}).forEach(function(var_name){if(match===false){var cellText=""+d[var_name];match=cellText.toLowerCase().indexOf(_this.searchable.searchTerm)>-1}});return match});this.data.processing=this.data.searched}else{delete this.data.searched;this.data.processing=this.data.filtered}}if(Array.prototype.equals)console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");Array.prototype.equals=function(array){if(!array)return false;if(this.length!=array.length)return false;for(var i=0,l=this.length;i=Math.max(widths.top,widths.bottom)&&this.config.layout==="vertical"){this.config.layout="horizontal";this.wrap.style("display","table").selectAll(".table-top,.table-bottom").style("display","block").selectAll(".interactivity").style({display:"inline-block",float:function float(){return select(this).classed("searchable-container")||select(this).classed("pagination-container")?"right":null},clear:null})}}function draw$1(passed_data){var _this=this;var table=this;var config=this.config;this.data.passed=passed_data;this.events.onPreprocess.call(this);if(!passed_data)applyFilters.call(this);else updateDataObject.call(this);checkFilters.call(this);applySearchTerm.call(this);this.searchable.wrap.select(".nNrecords").text(this.data.processing.length===this.data.raw.length?this.data.raw.length+" records displayed":this.data.processing.length+"/"+this.data.raw.length+" records displayed");updateTableHeaders.call(this);this.tbody.selectAll("tr").remove();if(this.data.processing.length===0){this.tbody.append("tr").classed("no-data",true).append("td").attr("colspan",this.config.cols.length).text("No data selected.");this.data.current=clone(this.data.processing);this.table.datum(this.table.current);if(this.config.exportable)this.config.exports.forEach(function(fmt){_this.exportable.exports[fmt].call(_this,_this.data.processing)});if(this.config.pagination)this.pagination.addPagination.call(this,this.data.processing)}else{if(this.config.sortable){this.thead.selectAll("th").on("click",function(header){table.sortable.onClick.call(table,this,header)});if(this.sortable.order.length)this.sortable.sortData.call(this,this.data.processing)}this.data.current=clone(this.data.processing);this.table.datum(this.data.current);if(this.config.exportable)this.config.exports.forEach(function(fmt){_this.exportable.exports[fmt].call(_this,_this.data.processing)});if(this.config.pagination){this.pagination.addPagination.call(this,this.data.processing);this.data.processing=this.data.processing.filter(function(d,i){return _this.config.startIndex<=i&&i<_this.config.endIndex})}drawTableBody.call(this)}dynamicLayout.call(this);this.events.onDraw.call(this)}function layout$2(){var context=this;this.searchable.wrap=this.wrap.select(".table-top").append("div").classed("interactivity searchable-container",true).classed("hidden",!this.config.searchable);this.searchable.wrap.append("div").classed("search",true);this.searchable.wrap.select(".search").append("input").classed("search-box",true).attr("placeholder","Search").on("input",function(){context.searchable.searchTerm=this.value.toLowerCase()||null;context.config.activePage=0;context.config.startIndex=context.config.activePage*context.config.nRowsPerPage;context.config.endIndex=context.config.startIndex+context.config.nRowsPerPage;context.draw()});this.searchable.wrap.select(".search").append("span").classed("nNrecords",true)}function searchable(){return{layout:layout$2}}function layout$3(){var _this=this;this.exportable.wrap=this.wrap.select(".table-bottom").append("div").classed("interactivity exportable-container",true).classed("hidden",!this.config.exportable);this.exportable.wrap.append("span").text("Export:");if(this.config.exports&&this.config.exports.length)this.config.exports.forEach(function(fmt){_this.exportable.wrap.append("a").classed("wc-button export",true).attr({id:fmt}).text(fmt.toUpperCase())})}function csv(data){var _this=this;var CSVarray=[];var headers=this.config.headers.map(function(header){return'"'+header.replace(/"/g,'""')+'"'});CSVarray.push(headers);data.forEach(function(d,i){var row=_this.config.cols.map(function(col){var value=d[col];if(typeof value==="string")value=value.replace(/"/g,'""');return'"'+value+'"'});CSVarray.push(row)});var CSV=new Blob([CSVarray.join("\n")],{type:"text/csv;charset=utf-8;"}),fileName="webchartsTableExport_"+d3.time.format("%Y-%m-%dT%H-%M-%S")(new Date)+".csv",link=this.wrap.select(".export#csv");if(navigator.msSaveBlob){link.style({cursor:"pointer","text-decoration":"underline",color:"blue"});link.on("click",function(){navigator.msSaveBlob(CSV,fileName)})}else{if(link.node().download!==undefined){var url=URL.createObjectURL(CSV);link.node().setAttribute("href",url);link.node().setAttribute("download",fileName)}}}function xlsx(data){var _this=this;var sheetName="Selected Data",options={bookType:"xlsx",bookSST:true,type:"binary"},arrayOfArrays=data.map(function(d){return Object.keys(d).filter(function(key){return _this.config.cols.indexOf(key)>-1}).map(function(key){return d[key]})}),workbook={SheetNames:[sheetName],Sheets:{}},cols=[];workbook.Sheets[sheetName]=XLSX.utils.aoa_to_sheet([this.config.headers].concat(arrayOfArrays));workbook.Sheets[sheetName]["!autofilter"]={ref:"A1:"+String.fromCharCode(64+this.config.cols.length)+(data.length+1)};this.table.selectAll("thead tr th").each(function(){cols.push({wpx:this.offsetWidth})});workbook.Sheets[sheetName]["!cols"]=cols;var xlsx=XLSX.write(workbook,options),s2ab=function s2ab(s){var buffer=new ArrayBuffer(s.length),view=new Uint8Array(buffer);for(var i=0;i!==s.length;++i){view[i]=s.charCodeAt(i)&255}return buffer};var blob=new Blob([s2ab(xlsx)],{type:"application/octet-stream;"}),fileName="webchartsTableExport_"+d3.time.format("%Y-%m-%dT%H-%M-%S")(new Date)+".xlsx",link=this.wrap.select(".export#xlsx");if(navigator.msSaveBlob){link.style({cursor:"pointer","text-decoration":"underline",color:"blue"});link.on("click",function(){navigator.msSaveBlob(blob,fileName)})}else{if(link.node().download!==undefined){var url=URL.createObjectURL(blob);link.node().setAttribute("href",url);link.node().setAttribute("download",fileName)}}}var exports$1={csv:csv,xlsx:xlsx};function exportable(){return{layout:layout$3,exports:exports$1}}function layout$4(){this.sortable.wrap=this.wrap.select(".table-top").append("div").classed("interactivity sortable-container",true).classed("hidden",!this.config.sortable);this.sortable.wrap.append("div").classed("instruction",true).text("Click column headers to sort.")}function onClick(th,header){var context=this,selection=d3.select(th),col=this.config.cols[this.config.headers.indexOf(header)];var sortItem=this.sortable.order.filter(function(item){return item.col===col})[0];if(!sortItem){sortItem={col:col,direction:"ascending",wrap:this.sortable.wrap.append("div").datum({key:col}).classed("wc-button sort-box",true).text(header)};sortItem.wrap.append("span").classed("sort-direction",true).html("↓");sortItem.wrap.append("span").classed("remove-sort",true).html("❌");this.sortable.order.push(sortItem)}else{sortItem.direction=sortItem.direction==="ascending"?"descending":"ascending";sortItem.wrap.select("span.sort-direction").html(sortItem.direction==="ascending"?"↓":"↑")}this.sortable.wrap.select(".instruction").classed("hidden",true);this.sortable.order.forEach(function(item,i){item.wrap.on("click",function(d){d3.select(this).remove();context.sortable.order.splice(context.sortable.order.map(function(d){return d.col}).indexOf(d.key),1);context.sortable.wrap.select(".instruction").classed("hidden",context.sortable.order.length);context.draw()})});this.draw()}function sortData(data){var _this=this;data=data.sort(function(a,b){var order=0;_this.sortable.order.forEach(function(item){var aCell=a[item.col],bCell=b[item.col];if(order===0){if(item.direction==="ascending"&&aCellbCell)order=-1;else if(item.direction==="ascending"&&aCell>bCell||item.direction==="descending"&&aCell=_this.config.nPageLinksDisplayed:_this.config.activePage>=_this.config.nPages-_this.config.nPageLinksDisplayed?i<_this.config.nPages-_this.config.nPageLinksDisplayed:i<_this.config.activePage-(Math.ceil(_this.config.nPageLinksDisplayed/2)-1)||_this.config.activePage+_this.config.nPageLinksDisplayed/2=this.config.nPages)next=this.config.nPages-1;this.pagination.wrap.insert("span",":first-child").classed("dot-dot-dot",true).text("...").classed("hidden",this.config.activePage=Math.max(this.config.nPageLinksDisplayed,this.config.nPages-this.config.nPageLinksDisplayed)||this.config.nPages<=this.config.nPageLinksDisplayed);this.pagination.next=this.pagination.wrap.append("a").classed("wc-button arrow-link wc-right",true).classed("hidden",this.config.activePage==this.config.nPages-1||this.config.nPages==0).attr({rel:next}).text(">");this.pagination.doubleNext=this.pagination.wrap.append("a").classed("wc-button arrow-link wc-right double",true).classed("hidden",this.config.activePage==this.config.nPages-1||this.config.nPages==0).attr({rel:this.config.nPages-1}).text(">>");this.pagination.arrows=this.pagination.wrap.selectAll("a.arrow-link");this.pagination.doubleArrows=this.pagination.wrap.selectAll("a.double-arrow-link")}function addPagination(data){var context=this;this.config.nRows=data.length;this.config.nPages=Math.ceil(this.config.nRows/this.config.nRowsPerPage);this.config.paginationHidden=this.config.nPages===1;this.pagination.wrap.classed("hidden",this.config.paginationHidden);addLinks.call(this);this.pagination.links.on("click",function(){context.config.activePage=+d3.select(this).attr("rel");updatePagination.call(context)});addArrows.call(this);this.pagination.arrows.on("click",function(){if(context.config.activePage!==+d3.select(this).attr("rel")){context.config.activePage=+d3.select(this).attr("rel");context.pagination.prev.attr("rel",context.config.activePage>0?context.config.activePage-1:0);context.pagination.next.attr("rel",context.config.activePage1&&arguments[1]!==undefined?arguments[1]:false;if(d3.select(this.div).select(".loader").empty()){d3.select(this.div).insert("div",":first-child").attr("class","loader").selectAll(".blockG").data(d3.range(8)).enter().append("div").attr("class",function(d){return"blockG rotate"+(d+1)})}this.setDefaults.call(this,data[0]);this.wrap.classed("wc-chart",true).classed("wc-table",this.config.applyCSS);this.data={raw:data};this.searchable=searchable.call(this);this.sortable=sortable.call(this);this.pagination=pagination.call(this);this.exportable=exportable.call(this);var startup=function startup(data){if(_this.controls){_this.controls.targets.push(_this);if(!_this.controls.ready){_this.controls.init(_this.data.raw)}else{_this.controls.layout()}}var visible=d3.select(_this.div).property("offsetWidth")>0||test;if(!visible){console.warn("The table cannot be initialized inside an element with 0 width. The table will be initialized as soon as the container element is given a width > 0.");var onVisible=setInterval(function(i){var visible_now=d3.select(_this.div).property("offsetWidth")>0;if(visible_now){_this.layout();_this.wrap.datum(_this);_this.draw();clearInterval(onVisible)}},500)}else{_this.layout();_this.wrap.datum(_this);_this.draw()}};this.events.onInit.call(this);if(this.data.raw.length){this.checkRequired(this.data.raw)}startup(data);return this}function layout$6(){d3.select(this.div).select(".loader").remove();this.wrap.append("div").classed("table-top",true);this.searchable.layout.call(this);this.sortable.layout.call(this);this.table=this.wrap.append("table").classed("table",this.config.bootstrap);this.thead=this.table.append("thead");this.thead.append("tr");this.tbody=this.table.append("tbody");this.wrap.append("div").classed("table-bottom",true);this.pagination.layout.call(this);this.exportable.layout.call(this);this.events.onLayout.call(this)}function destroy$2(){var destroyControls=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;this.events.onDestroy.call(this);if(destroyControls&&this.controls){this.controls.destroy()}this.wrap.remove()}function setDefault(setting){var _default_=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;this.config[setting]=this.config[setting]!==undefined?this.config[setting]:_default_}function setDefaults$1(firstItem){if(this.config.cols instanceof Array&&this.config.headers instanceof Array){if(this.config.cols.length===0)delete this.config.cols;if(this.config.headers.length===0||this.config.headers.length!==this.config.cols.length)delete this.config.headers}this.config.cols=this.config.cols||d3.keys(firstItem);this.config.headers=this.config.headers||this.config.cols;this.config.layout="horizontal";setDefault.call(this,"searchable");setDefault.call(this,"exportable");setDefault.call(this,"exports",["csv"]);setDefault.call(this,"sortable");setDefault.call(this,"pagination");setDefault.call(this,"nRowsPerPage",10);setDefault.call(this,"nPageLinksDisplayed",5);setDefault.call(this,"applyCSS")}function transformData$1(processed_data){var _this=this;this.data.processed=this.transformData(this.wrap.datum);if(!data){return}this.config.cols=this.config.cols||d3.keys(data[0]);this.config.headers=this.config.headers||this.config.cols;if(this.config.keep){this.config.keep.forEach(function(e){if(_this.config.cols.indexOf(e)===-1){_this.config.cols.unshift(e)}})}var filtered=data;if(this.filters.length){this.filters.forEach(function(e){var is_array=e.val instanceof Array;filtered=filtered.filter(function(d){if(is_array){return e.val.indexOf(d[e.col])!==-1}else{return e.val!=="All"?d[e.col]===e.val:d}})})}var slimmed=d3.nest().key(function(d){if(_this.config.row_per){return _this.config.row_per.map(function(m){return d[m]}).join(" ")}else{return d}}).rollup(function(r){if(_this.config.dataManipulate){r=_this.config.dataManipulate(r)}var nuarr=r.map(function(m){var arr=[];for(var x in m){arr.push({col:x,text:m[x]})}arr.sort(function(a,b){return _this.config.cols.indexOf(a.col)-_this.config.cols.indexOf(b.col)});return{cells:arr,raw:m}});return nuarr}).entries(filtered);this.data.current=slimmed.length?slimmed:[{key:null,values:[]}];this.pagination.wrap.selectAll("*").remove();this.events.onDatatransform.call(this);if(config.row_per){var rev_order=config.row_per.slice(0).reverse();rev_order.forEach(function(e){tbodies.sort(function(a,b){return a.values[0].raw[e]-b.values[0].raw[e]})})}if(config.row_per){rows.filter(function(f,i){return i>0}).selectAll("td").filter(function(f){return config.row_per.indexOf(f.col)>-1}).text("")}return this.data.current}var table=Object.create(chart,{draw:{value:draw$1},init:{value:init$2},layout:{value:layout$6},setDefaults:{value:setDefaults$1},transformData:{value:transformData$1},destroy:{value:destroy$2}});function createTable(){var element=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var controls=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var thisTable=Object.create(table);thisTable.div=element;thisTable.config=Object.create(config);thisTable.controls=controls;thisTable.filters=[];thisTable.required_cols=[];thisTable.wrap=d3.select(thisTable.div).append("div").datum(thisTable);thisTable.events={onInit:function onInit(){},onLayout:function onLayout(){},onPreprocess:function onPreprocess(){},onDraw:function onDraw(){},onDestroy:function onDestroy(){}};thisTable.on=function(event,callback){var possible_events=["init","layout","preprocess","draw","destroy"];if(possible_events.indexOf(event)<0){return}if(callback){thisTable.events["on"+event.charAt(0).toUpperCase()+event.slice(1)]=callback}};return thisTable}function multiply(chart,data,split_by,order){var test=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;chart.wrap.classed("wc-layout wc-small-multiples",true).classed("wc-chart",false);chart.master_legend=chart.wrap.append("ul").attr("class","legend");chart.master_legend.append("span").classed("legend-title",true);chart.multiples=[];function goAhead(data){var split_vals=d3.set(data.map(function(m){return m[split_by]})).values().filter(function(f){return f});if(order){split_vals=split_vals.sort(function(a,b){return d3.ascending(order.indexOf(a),order.indexOf(b))})}split_vals.forEach(function(e){var mchart=createChart(chart.wrap.node(),chart.config,chart.controls);chart.multiples.push(mchart);mchart.parent=chart;mchart.events=chart.events;mchart.legend=chart.master_legend;mchart.filters.unshift({col:split_by,val:e,choices:split_vals});mchart.wrap.insert("span","svg").attr("class","wc-chart-title").text(e);mchart.init(data,test)})}goAhead(data)}function getValType(data,variable){var var_vals=d3.set(data.map(function(m){return m[variable]})).values();var vals_numbers=var_vals.filter(function(f){return+f||+f===0});if(var_vals.length===vals_numbers.length&&var_vals.length>4){return"continuous"}else{return"categorical"}}function lengthenRaw(data,columns){var my_data=[];data.forEach(function(e){columns.forEach(function(g){var obj=Object.create(e);obj.wc_category=g;obj.wc_value=e[g];my_data.push(obj)})});return my_data}var dataOps={getValType:getValType,lengthenRaw:lengthenRaw,naturalSorter:naturalSorter,summarize:summarize};var index={version:version,createChart:createChart,createControls:createControls,createTable:createTable,multiply:multiply,dataOps:dataOps};return index});
+(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory(require("d3")):typeof define==="function"&&define.amd?define(["d3"],factory):global.webCharts=factory(global.d3)})(this,function(d3){"use strict";var version="1.10.0";function checkRequired(data){var _this=this;var colnames=Object.keys(data[0]);var requiredVars=[];var requiredCols=[];if(this.config.x&&this.config.x.column){requiredVars.push("this.config.x.column");requiredCols.push(this.config.x.column)}if(this.config.y&&this.config.y.column){requiredVars.push("this.config.y.column");requiredCols.push(this.config.y.column)}if(this.config.color_by){requiredVars.push("this.config.color_by");requiredCols.push(this.config.color_by)}if(this.config.marks)this.config.marks.forEach(function(e,i){if(e.per&&e.per.length){e.per.forEach(function(p,j){requiredVars.push("this.config.marks["+i+"].per["+j+"]");requiredCols.push(p)})}if(e.split){requiredVars.push("this.config.marks["+i+"].split");requiredCols.push(e.split)}if(e.values){for(var value in e.values){requiredVars.push("this.config.marks["+i+"].values['"+value+"']");requiredCols.push(value)}}});var missingDataField=false;requiredCols.forEach(function(e,i){if(colnames.indexOf(e)<0){missingDataField=true;d3.select(_this.div).select(".loader").remove();_this.wrap.append("div").style("color","red").html('The value "'+e+'" for the '+requiredVars[i]+"
setting does not match any column in the provided dataset.");throw new Error('Error in settings object: The value "'+e+'" for the '+requiredVars[i]+" setting does not match any column in the provided dataset.")}});return{missingDataField:missingDataField,dataFieldArguments:requiredVars,requiredDataFields:requiredCols}}function naturalSorter(a,b){function chunkify(t){var tz=[];var x=0,y=-1,n=0,i=void 0,j=void 0;while(i=(j=t.charAt(x++)).charCodeAt(0)){var m=i==46||i>=48&&i<=57;if(m!==n){tz[++y]="";n=m}tz[y]+=j}return tz}var aa=chunkify(a.toLowerCase());var bb=chunkify(b.toLowerCase());for(var x=0;aa[x]&&bb[x];x++){if(aa[x]!==bb[x]){var c=Number(aa[x]),d=Number(bb[x]);if(c==aa[x]&&d==bb[x]){return c-d}else{return aa[x]>bb[x]?1:-1}}}return aa.length-bb.length}function consolidateData(raw){var _this=this;var config=this.config;var all_data=[];var all_x=[];var all_y=[];this.setDefaults();this.filtered_data=raw;if(this.filters.length){this.filters.forEach(function(e){_this.filtered_data=_this.filtered_data.filter(function(d){return e.val==="All"?d:e.val instanceof Array?e.val.indexOf(d[e.col])>-1:d[e.col]===e.val})})}config.marks.forEach(function(e,i){if(e.type!=="bar"){e.arrange=null;e.split=null}var mark_info=e.per?_this.transformData(raw,e):{data:[],x_dom:[],y_dom:[]};all_data.push(mark_info.data);all_x.push(mark_info.x_dom);all_y.push(mark_info.y_dom);_this.marks[i]={id:e.id,type:e.type,per:e.per,data:mark_info.data,split:e.split,text:e.text,arrange:e.arrange,order:e.order,summarizeX:e.summarizeX,summarizeY:e.summarizeY,tooltip:e.tooltip,radius:e.radius,attributes:e.attributes,values:e.values}});if(config.x.type==="ordinal"){if(config.x.domain){this.x_dom=config.x.domain}else if(config.x.order){this.x_dom=d3.set(d3.merge(all_x)).values().sort(function(a,b){return d3.ascending(config.x.order.indexOf(a),config.x.order.indexOf(b))})}else if(config.x.sort&&config.x.sort==="alphabetical-ascending"){this.x_dom=d3.set(d3.merge(all_x)).values().sort(naturalSorter)}else if(config.y.type==="time"&&config.x.sort==="earliest"){this.x_dom=d3.nest().key(function(d){return d[config.x.column]}).rollup(function(d){return d.map(function(m){return m[config.y.column]}).filter(function(f){return f instanceof Date})}).entries(this.raw_data).sort(function(a,b){return d3.min(b.values)-d3.min(a.values)}).map(function(m){return m.key})}else if(!config.x.sort||config.x.sort==="alphabetical-descending"){this.x_dom=d3.set(d3.merge(all_x)).values().sort(naturalSorter)}else{this.x_dom=d3.set(d3.merge(all_x)).values()}}else if(config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1){this.x_dom=[0,1]}else{this.x_dom=d3.extent(d3.merge(all_x))}if(config.y.type==="ordinal"){if(config.y.domain){this.y_dom=config.y.domain}else if(config.y.order){this.y_dom=d3.set(d3.merge(all_y)).values().sort(function(a,b){return d3.ascending(config.y.order.indexOf(a),config.y.order.indexOf(b))})}else if(config.y.sort&&config.y.sort==="alphabetical-ascending"){this.y_dom=d3.set(d3.merge(all_y)).values().sort(naturalSorter)}else if(config.x.type==="time"&&config.y.sort==="earliest"){this.y_dom=d3.nest().key(function(d){return d[config.y.column]}).rollup(function(d){return d.map(function(m){return m[config.x.column]}).filter(function(f){return f instanceof Date})}).entries(this.raw_data).sort(function(a,b){return d3.min(b.values)-d3.min(a.values)}).map(function(m){return m.key})}else if(!config.y.sort||config.y.sort==="alphabetical-descending"){this.y_dom=d3.set(d3.merge(all_y)).values().sort(naturalSorter).reverse()}else{this.y_dom=d3.set(d3.merge(all_y)).values()}}else if(config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1){this.y_dom=[0,1]}else{this.y_dom=d3.extent(d3.merge(all_y))}}function destroy(){var destroyControls=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;this.events.onDestroy.call(this);var context=this;d3.select(window).on("resize."+context.element+context.id,null);if(destroyControls&&this.controls){this.controls.destroy()}this.wrap.remove()}function draw(raw_data,processed_data){var _this=this;var context=this;var config=this.config;var aspect2=1/config.aspect;this.events.onPreprocess.call(this);var raw=raw_data?raw_data:this.raw_data?this.raw_data:[];if(processed_data){console.warn("Drawing the chart using user-defined 'processed_data', this is an experimental, untested feature.")}var data=processed_data||this.consolidateData(raw);var div_width=parseInt(this.wrap.style("width"));this.setColorScale();var max_width=config.max_width?config.max_width:div_width;this.raw_width=config.x.type==="ordinal"&&+config.range_band?(+config.range_band+config.range_band*config.padding)*this.x_dom.length:config.resizable?max_width:config.width?config.width:div_width;this.raw_height=config.y.type==="ordinal"&&+config.range_band?(+config.range_band+config.range_band*config.padding)*this.y_dom.length:config.resizable?max_width*aspect2:config.height?config.height:div_width*aspect2;var pseudo_width=this.svg.select(".overlay").attr("width")?this.svg.select(".overlay").attr("width"):this.raw_width;var pseudo_height=this.svg.select(".overlay").attr("height")?this.svg.select(".overlay").attr("height"):this.raw_height;this.svg.select(".x.axis").select(".axis-title").text(function(d){return typeof config.x.label==="string"?config.x.label:typeof config.x.label==="function"?config.x.label.call(_this):null});this.svg.select(".y.axis").select(".axis-title").text(function(d){return typeof config.y.label==="string"?config.y.label:typeof config.y.label==="function"?config.y.label.call(_this):null});this.xScaleAxis(pseudo_width);this.yScaleAxis(pseudo_height);if(config.resizable&&typeof window!=="undefined"){d3.select(window).on("resize."+context.element+context.id,function(){context.resize()})}else if(typeof window!=="undefined"){d3.select(window).on("resize."+context.element+context.id,null)}this.events.onDraw.call(this);this.resize()}function drawArea(area_drawer,area_data,datum_accessor){var class_match=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"chart-area";var _this=this;var bind_accessor=arguments[4];var attr_accessor=arguments.length>5&&arguments[5]!==undefined?arguments[5]:function(d){return d};var area_grps=this.svg.selectAll("."+class_match).data(area_data,bind_accessor);area_grps.exit().remove();area_grps.enter().append("g").attr("class",function(d){return class_match+" "+d.key}).append("path");var areaPaths=area_grps.select("path").datum(datum_accessor).attr("fill",function(d){var d_attr=attr_accessor(d);return d_attr?_this.colorScale(d_attr[_this.config.color_by]):null}).attr("fill-opacity",this.config.fill_opacity||this.config.fill_opacity===0?this.config.fill_opacity:.3);var areaPathTransitions=this.config.transitions?areaPaths.transition():areaPaths;areaPathTransitions.attr("d",area_drawer);return area_grps}function drawBars(marks){var _this=this;var rawData=this.raw_data;var config=this.config;var bar_supergroups=this.svg.selectAll(".bar-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});bar_supergroups.enter().append("g").attr("class",function(d){return"supergroup bar-supergroup "+d.id});bar_supergroups.exit().remove();var bar_groups=bar_supergroups.selectAll(".bar-group").data(function(d){return d.data},function(d){return d.key});var old_bar_groups=bar_groups.exit();var nu_bar_groups=void 0;var bars=void 0;var oldBarsTrans=config.transitions?old_bar_groups.selectAll(".bar").transition():old_bar_groups.selectAll(".bar");var oldBarGroupsTrans=config.transitions?old_bar_groups.transition():old_bar_groups;if(config.x.type==="ordinal"){oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values.sort(function(a,b){return _this.colorScale.domain().indexOf(b.key)-_this.colorScale.domain().indexOf(a.key)}):[d]},function(d){return d.key});var exitBars=config.transitions?bars.exit().transition():bars.exit();exitBars.attr("y",this.y(0)).attr("height",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("y",this.y(0)).attr("height",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.tooltip=mark.tooltip;d.arrange=mark.split?mark.arrange:null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d3.select(this).attr(mark.attributes)});var xformat=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var yformat=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,xformat(d.values.x)).replace(/\$y/g,yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var barsTrans=config.transitions?bars.transition():bars;barsTrans.attr("x",function(d){var position=void 0;if(!d.arrange||d.arrange==="stacked"){return _this.x(d.values.x)}else if(d.arrange==="nested"){var _position=d.subcats.indexOf(d.key);var offset=_position?_this.x.rangeBand()/(d.subcats.length*.75)/_position:_this.x.rangeBand();return _this.x(d.values.x)+(_this.x.rangeBand()-offset)/2}else{position=d.subcats.indexOf(d.key);return _this.x(d.values.x)+_this.x.rangeBand()/d.subcats.length*position}}).attr("y",function(d){if(d.arrange!=="stacked"){return _this.y(d.values.y)}else{return _this.y(d.values.start)}}).attr("width",function(d){if(!d.arrange||d.arrange==="stacked"){return _this.x.rangeBand()}else if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);return position?_this.x.rangeBand()/(d.subcats.length*.75)/position:_this.x.rangeBand()}else{return _this.x.rangeBand()/d.subcats.length}}).attr("height",function(d){return _this.y(0)-_this.y(d.values.y)})}else if(config.y.type==="ordinal"){oldBarsTrans.attr("x",this.x(0)).attr("width",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values.sort(function(a,b){return _this.colorScale.domain().indexOf(b.key)-_this.colorScale.domain().indexOf(a.key)}):[d]},function(d){return d.key});var _exitBars=config.transitions?bars.exit().transition():bars.exit();_exitBars.attr("x",this.x(0)).attr("width",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("x",this.x(0)).attr("width",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split&&mark.arrange?mark.arrange:mark.split?"grouped":null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d.tooltip=mark.tooltip});var _xformat=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat(d.values.x)).replace(/\$y/g,_yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans=config.transitions?bars.transition():bars;_barsTrans.attr("x",function(d){if(d.arrange==="stacked"||!d.arrange){return d.values.start!==undefined?_this.x(d.values.start):_this.x(0)}else{return _this.x(0)}}).attr("y",function(d){if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);var offset=position?_this.y.rangeBand()/(d.subcats.length*.75)/position:_this.y.rangeBand();return _this.y(d.values.y)+(_this.y.rangeBand()-offset)/2}else if(d.arrange==="grouped"){var _position2=d.subcats.indexOf(d.key);return _this.y(d.values.y)+_this.y.rangeBand()/d.subcats.length*_position2}else{return _this.y(d.values.y)}}).attr("width",function(d){return _this.x(d.values.x)-_this.x(0)}).attr("height",function(d){if(config.y.type==="quantile"){return 20}else if(d.arrange==="nested"){var position=d.subcats.indexOf(d.key);return position?_this.y.rangeBand()/(d.subcats.length*.75)/position:_this.y.rangeBand()}else if(d.arrange==="grouped"){return _this.y.rangeBand()/d.subcats.length}else{return _this.y.rangeBand()}})}else if(["linear","log"].indexOf(config.x.type)>-1&&config.x.bin){oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values:[d]},function(d){return d.key});var _exitBars2=config.transitions?bars.exit().transition():bars.exit();_exitBars2.attr("y",this.y(0)).attr("height",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("y",this.y(0)).attr("height",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split?mark.arrange:null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();d3.select(this).attr(mark.attributes);var parent=d3.select(this.parentNode).datum();var rangeSet=parent.key.split(",").map(function(m){return+m});d.rangeLow=d3.min(rangeSet);d.rangeHigh=d3.max(rangeSet);d.tooltip=mark.tooltip});var _xformat2=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat2=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat2(d.values.x)).replace(/\$y/g,_yformat2(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans2=config.transitions?bars.transition():bars;_barsTrans2.attr("x",function(d){return _this.x(d.rangeLow)}).attr("y",function(d){if(d.arrange!=="stacked"){return _this.y(d.values.y)}else{return _this.y(d.values.start)}}).attr("width",function(d){return _this.x(d.rangeHigh)-_this.x(d.rangeLow)}).attr("height",function(d){return _this.y(0)-_this.y(d.values.y)})}else if(["linear","log"].indexOf(config.y.type)>-1&&config.y.type==="linear"&&config.y.bin){oldBarsTrans.attr("x",this.x(0)).attr("width",0);oldBarGroupsTrans.remove();nu_bar_groups=bar_groups.enter().append("g").attr("class",function(d){return"bar-group "+d.key});nu_bar_groups.append("title");bars=bar_groups.selectAll("rect").data(function(d){return d.values instanceof Array?d.values:[d]},function(d){return d.key});var _exitBars3=config.transitions?bars.exit().transition():bars.exit();_exitBars3.attr("x",this.x(0)).attr("width",0).remove();bars.enter().append("rect").attr("class",function(d){return"wc-data-mark bar "+d.key}).style("clip-path","url(#"+this.id+")").attr("x",this.x(0)).attr("width",0).append("title");bars.attr("shape-rendering","crispEdges").attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});bars.each(function(d){var mark=d3.select(this.parentNode.parentNode).datum();d.arrange=mark.split?mark.arrange:null;d.subcats=config.legend.order?config.legend.order.slice().reverse():mark.values&&mark.values[mark.split]?mark.values[mark.split]:d3.set(rawData.map(function(m){return m[mark.split]})).values();var parent=d3.select(this.parentNode).datum();var rangeSet=parent.key.split(",").map(function(m){return+m});d.rangeLow=d3.min(rangeSet);d.rangeHigh=d3.max(rangeSet);d.tooltip=mark.tooltip});var _xformat3=config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.x.format);var _yformat3=config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?d3.format("0%"):d3.format(config.y.format);bars.select("title").text(function(d){var tt=d.tooltip||"";return tt.replace(/\$x/g,_xformat3(d.values.x)).replace(/\$y/g,_yformat3(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var _barsTrans3=config.transitions?bars.transition():bars;_barsTrans3.attr("x",function(d){if(d.arrange==="stacked"){return _this.x(d.values.start)}else{return _this.x(0)}}).attr("y",function(d){return _this.y(d.rangeHigh)}).attr("width",function(d){return _this.x(d.values.x)}).attr("height",function(d){return _this.y(d.rangeLow)-_this.y(d.rangeHigh)})}else{oldBarsTrans.attr("y",this.y(0)).attr("height",0);oldBarGroupsTrans.remove();bar_supergroups.remove()}bar_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll(".bar-group")})}function drawGridLines(){this.wrap.classed("gridlines",this.config.gridlines);if(this.config.gridlines){this.svg.select(".y.axis").selectAll(".tick line").attr("x1",0);this.svg.select(".x.axis").selectAll(".tick line").attr("y1",0);if(this.config.gridlines==="y"||this.config.gridlines==="xy")this.svg.select(".y.axis").selectAll(".tick line").attr("x1",this.plot_width);if(this.config.gridlines==="x"||this.config.gridlines==="xy")this.svg.select(".x.axis").selectAll(".tick line").attr("y1",-this.plot_height)}else{this.svg.select(".y.axis").selectAll(".tick line").attr("x1",0);this.svg.select(".x.axis").selectAll(".tick line").attr("y1",0)}}function drawLines(marks){var _this=this;var config=this.config;var line=d3.svg.line().interpolate(config.interpolate).x(function(d){return config.x.type==="linear"||config.x.type=="log"?_this.x(+d.values.x):config.x.type==="time"?_this.x(new Date(d.values.x)):_this.x(d.values.x)+_this.x.rangeBand()/2}).y(function(d){return config.y.type==="linear"||config.y.type=="log"?_this.y(+d.values.y):config.y.type==="time"?_this.y(new Date(d.values.y)):_this.y(d.values.y)+_this.y.rangeBand()/2});var line_supergroups=this.svg.selectAll(".line-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});line_supergroups.enter().append("g").attr("class",function(d){return"supergroup line-supergroup "+d.id});line_supergroups.exit().remove();var line_grps=line_supergroups.selectAll(".line").data(function(d){return d.data},function(d){return d.key});line_grps.exit().remove();var nu_line_grps=line_grps.enter().append("g").attr("class",function(d){return d.key+" line"});nu_line_grps.append("path");nu_line_grps.append("title");var linePaths=line_grps.select("path").attr("class","wc-data-mark").datum(function(d){return d.values}).attr("stroke",function(d){return _this.colorScale(d[0].values.raw[0][config.color_by])}).attr("stroke-width",config.stroke_width?config.stroke_width:config.flex_stroke_width).attr("stroke-linecap","round").attr("fill","none");var linePathsTrans=config.transitions?linePaths.transition():linePaths;linePathsTrans.attr("d",line);line_grps.each(function(d){var mark=d3.select(this.parentNode).datum();d.tooltip=mark.tooltip;d3.select(this).select("path").attr(mark.attributes)});line_grps.select("title").text(function(d){var tt=d.tooltip||"";var xformat=config.x.summary==="percent"?d3.format("0%"):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):d3.format(config.y.format);return tt.replace(/\$x/g,xformat(d.values.x)).replace(/\$y/g,yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values[0].values.raw[0][orig]})});line_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.line");d.paths=d.groups.select("path")});return line_grps}function drawPoints(marks){var _this=this;var config=this.config;var point_supergroups=this.svg.selectAll(".point-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});point_supergroups.enter().append("g").attr("class",function(d){return"supergroup point-supergroup "+d.id});point_supergroups.exit().remove();var points=point_supergroups.selectAll(".point").data(function(d){return d.data},function(d){return d.key});var oldPoints=points.exit();var oldPointsTrans=config.transitions?oldPoints.selectAll("circle").transition():oldPoints.selectAll("circle");oldPointsTrans.attr("r",0);var oldPointGroupTrans=config.transitions?oldPoints.transition():oldPoints;oldPointGroupTrans.remove();var nupoints=points.enter().append("g").attr("class",function(d){return d.key+" point"});nupoints.append("circle").attr("class","wc-data-mark").attr("r",0);nupoints.append("title");points.select("circle").attr("fill-opacity",config.fill_opacity||config.fill_opacity===0?config.fill_opacity:.6).attr("fill",function(d){return _this.colorScale(d.values.raw[0][config.color_by])}).attr("stroke",function(d){return _this.colorScale(d.values.raw[0][config.color_by])});points.each(function(d){var mark=d3.select(this.parentNode).datum();d.mark=mark;d3.select(this).select("circle").attr(mark.attributes)});var pointsTrans=config.transitions?points.select("circle").transition():points.select("circle");pointsTrans.attr("r",function(d){return d.mark.radius||config.flex_point_size}).attr("cx",function(d){var x_pos=_this.x(d.values.x)||0;return config.x.type==="ordinal"?x_pos+_this.x.rangeBand()/2:x_pos}).attr("cy",function(d){var y_pos=_this.y(d.values.y)||0;return config.y.type==="ordinal"?y_pos+_this.y.rangeBand()/2:y_pos});points.select("title").text(function(d){var tt=d.mark.tooltip||"";var xformat=config.x.summary==="percent"?d3.format("0%"):config.x.type==="time"?d3.time.format(config.x.format):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):config.y.type==="time"?d3.time.format(config.y.format):d3.format(config.y.format);return tt.replace(/\$x/g,config.x.type==="time"?xformat(new Date(d.values.x)):xformat(d.values.x)).replace(/\$y/g,config.y.type==="time"?yformat(new Date(d.values.y)):yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});point_supergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.point");d.circles=d.groups.select("circle")});return points}function drawText(marks){var _this=this;var config=this.config;var textSupergroups=this.svg.selectAll(".text-supergroup").data(marks,function(d,i){return i+"-"+d.per.join("-")});textSupergroups.enter().append("g").attr("class",function(d){return"supergroup text-supergroup "+d.id});textSupergroups.exit().remove();var texts=textSupergroups.selectAll(".text").data(function(d){return d.data},function(d){return d.key});var oldTexts=texts.exit();var oldTextGroupTrans=config.transitions?oldTexts.transition():oldTexts;oldTextGroupTrans.remove();var nutexts=texts.enter().append("g").attr("class",function(d){return d.key+" text"});nutexts.append("text").attr("class","wc-data-mark");function attachMarks(d){d.mark=d3.select(this.parentNode).datum();d3.select(this).select("text").attr(d.mark.attributes)}texts.each(attachMarks);texts.select("text").text(function(d){var tt=d.mark.text||"";var xformat=config.x.summary==="percent"?d3.format("0%"):config.x.type==="time"?d3.time.format(config.x.format):d3.format(config.x.format);var yformat=config.y.summary==="percent"?d3.format("0%"):config.y.type==="time"?d3.time.format(config.y.format):d3.format(config.y.format);return tt.replace(/\$x/g,config.x.type==="time"?xformat(new Date(d.values.x)):xformat(d.values.x)).replace(/\$y/g,config.y.type==="time"?yformat(new Date(d.values.y)):yformat(d.values.y)).replace(/\[(.+?)\]/g,function(str,orig){return d.values.raw[0][orig]})});var textsTrans=config.transitions?texts.select("text").transition():texts.select("text");textsTrans.attr("x",function(d){var xPos=_this.x(d.values.x)||0;return config.x.type==="ordinal"?xPos+_this.x.rangeBand()/2:xPos}).attr("y",function(d){var yPos=_this.y(d.values.y)||0;return config.y.type==="ordinal"?yPos+_this.y.rangeBand()/2:yPos});textSupergroups.each(function(d){d.supergroup=d3.select(this);d.groups=d.supergroup.selectAll("g.text");d.texts=d.groups.select("text")});return texts}function init(data){var _this=this;var test=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;if(d3.select(this.div).select(".loader").empty()){d3.select(this.div).insert("div",":first-child").attr("class","loader").selectAll(".blockG").data(d3.range(8)).enter().append("div").attr("class",function(d){return"blockG rotate"+(d+1)})}this.wrap.attr("class","wc-chart");this.setDefaults();this.raw_data=data;this.initial_data=data;var startup=function startup(data){if(_this.controls){_this.controls.targets.push(_this);if(!_this.controls.ready){_this.controls.init(_this.raw_data)}else{_this.controls.layout()}}var visible=d3.select(_this.div).property("offsetWidth")>0||test;if(!visible){console.warn("The chart cannot be initialized inside an element with 0 width. The chart will be initialized as soon as the container element is given a width > 0.");var onVisible=setInterval(function(i){var visible_now=d3.select(_this.div).property("offsetWidth")>0;if(visible_now){_this.layout();_this.draw();clearInterval(onVisible)}},500)}else{_this.layout();_this.draw()}};this.events.onInit.call(this);if(this.raw_data.length){this.checkRequired(this.raw_data)}startup(data);return this}function layout(){this.svg=this.wrap.append("svg").attr({class:"wc-svg",xmlns:"http://www.w3.org/2000/svg",version:"1.1",xlink:"http://www.w3.org/1999/xlink"}).append("g").style("display","inline-block");var defs=this.svg.append("defs");defs.append("pattern").attr({id:"diagonal-stripes",x:0,y:0,width:3,height:8,patternUnits:"userSpaceOnUse",patternTransform:"rotate(30)"}).append("rect").attr({x:"0",y:"0",width:"2",height:"8",style:"stroke:none; fill:black"});defs.append("clipPath").attr("id",this.id).append("rect").attr("class","plotting-area");this.svg.append("g").attr("class","y axis").append("text").attr("class","axis-title").attr("transform","rotate(-90)").attr("dy",".75em").attr("text-anchor","middle");this.svg.append("g").attr("class","x axis").append("text").attr("class","axis-title").attr("dy","-.35em").attr("text-anchor","middle");this.svg.append("rect").attr("class","overlay").attr("opacity",0).attr("fill","none").style("pointer-events","all");var legend=this.wrap.append("ul");legend.attr("class","legend").style("vertical-align","top").append("span").attr("class","legend-title");d3.select(this.div).select(".loader").remove();this.events.onLayout.call(this)}function makeLegend(){var scale$$1=arguments.length>0&&arguments[0]!==undefined?arguments[0]:this.colorScale;var label=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var custom_data=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var config=this.config;config.legend.mark=config.legend.mark?config.legend.mark:config.marks.length&&config.marks[0].type==="bar"?"square":config.marks.length?config.marks[0].type:"square";var legend_label=label?label:typeof config.legend.label==="string"?config.legend.label:"";var legendOriginal=this.legend||this.wrap.select(".legend");var legend=legendOriginal;if(this.config.legend.location==="top"||this.config.legend.location==="left"){this.wrap.node().insertBefore(legendOriginal.node(),this.svg.node().parentNode)}else{this.wrap.node().appendChild(legendOriginal.node())}legend.style("padding",0);var legend_data=custom_data||scale$$1.domain().slice(0).filter(function(f){return f!==undefined&&f!==null}).map(function(m){return{label:m,mark:config.legend.mark}});legend.select(".legend-title").text(legend_label).style("display",legend_label?"inline":"none").style("margin-right","1em");var leg_parts=legend.selectAll(".legend-item").data(legend_data,function(d){return d.label+d.mark});leg_parts.exit().remove();var legendPartDisplay=this.config.legend.location==="bottom"||this.config.legend.location==="top"?"inline-block":"block";var new_parts=leg_parts.enter().append("li").attr("class","legend-item").style({"list-style-type":"none","margin-right":"1em"});new_parts.append("span").attr("class","legend-mark-text").style("color",function(d){return scale$$1(d.label)});new_parts.append("svg").attr("class","legend-color-block").attr("width","1.1em").attr("height","1.1em").style({position:"relative",top:"0.2em"});leg_parts.style("display",legendPartDisplay);if(config.legend.order){leg_parts.sort(function(a,b){return d3.ascending(config.legend.order.indexOf(a.label),config.legend.order.indexOf(b.label))})}leg_parts.selectAll(".legend-color-block").select(".legend-mark").remove();leg_parts.selectAll(".legend-color-block").each(function(e){var svg$$1=d3.select(this);if(e.mark==="circle"){svg$$1.append("circle").attr({cx:".5em",cy:".45em",r:".45em",class:"legend-mark"})}else if(e.mark==="line"){svg$$1.append("line").attr({x1:0,y1:".5em",x2:"1em",y2:".5em","stroke-width":2,"shape-rendering":"crispEdges",class:"legend-mark"})}else if(e.mark==="square"){svg$$1.append("rect").attr({height:"1em",width:"1em",class:"legend-mark","shape-rendering":"crispEdges"})}});leg_parts.selectAll(".legend-color-block").select(".legend-mark").attr("fill",function(d){return d.color||scale$$1(d.label)}).attr("stroke",function(d){return d.color||scale$$1(d.label)}).each(function(e){d3.select(this).attr(e.attributes)})
+;new_parts.append("span").attr("class","legend-label").style("margin-left","0.25em").text(function(d){return d.label});if(scale$$1.domain().length>0){var legendDisplay=this.config.legend.location==="bottom"||this.config.legend.location==="top"?"block":"inline-block";legend.style("display",legendDisplay)}else{legend.style("display","none")}this.legend=legend}function resize(){var config=this.config;var aspect2=1/config.aspect;var div_width=parseInt(this.wrap.style("width"));var max_width=config.max_width?config.max_width:div_width;var preWidth=!config.resizable?config.width:!max_width||div_width-1){max_y_text_length+=1}max_y_text_length=Math.max(2,max_y_text_length);var x_label_on=this.config.x.label?1.5:0;var y_label_on=this.config.y.label?1.5:.25;var font_size=parseInt(this.wrap.style("font-size"));var x_second=this.config.x2_interval?1:0;var y_margin=max_y_text_length*font_size*.5+font_size*y_label_on*1.5||8;var x_margin=font_size+font_size/1.5+font_size*x_label_on+font_size*x_second||8;y_margin+=6;x_margin+=3;return{top:this.config.margin&&this.config.margin.top?this.config.margin.top:8,right:this.config.margin&&this.config.margin.right?this.config.margin.right:16,bottom:this.config.margin&&this.config.margin.bottom?this.config.margin.bottom:x_margin,left:this.config.margin&&this.config.margin.left?this.config.margin.left:y_margin}}function textSize(width){var font_size="14px";var point_size=4;var stroke_width=2;if(!this.config.scale_text){font_size=this.config.font_size;point_size=this.config.point_size||4;stroke_width=this.config.stroke_width||2}else if(width>=600){font_size="14px";point_size=4;stroke_width=2}else if(width>450&&width<600){font_size="12px";point_size=3;stroke_width=2}else if(width>300&&width<450){font_size="10px";point_size=2;stroke_width=2}else if(width<=300){font_size="10px";point_size=2;stroke_width=1}this.wrap.style("font-size",font_size);this.config.flex_point_size=point_size;this.config.flex_stroke_width=stroke_width}var stats={mean:d3.mean,min:d3.min,max:d3.max,median:d3.median,sum:d3.sum};function summarize(vals){var operation=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"mean";var nvals=vals.filter(function(f){return+f||+f===0}).map(function(m){return+m});if(operation==="cumulative"){return null}var mathed=operation==="count"?vals.length:operation==="percent"?vals.length:stats[operation](nvals);return mathed}function transformData(raw,mark){var _this=this;var config=this.config;var x_behavior=config.x.behavior||"raw";var y_behavior=config.y.behavior||"raw";var sublevel=mark.type==="line"?config.x.column:mark.type==="bar"&&mark.split?mark.split:null;var dateConvert=d3.time.format(config.date_format);var totalOrder=void 0;function calcStartTotal(e){var axis=config.x.type==="ordinal"||config.x.type==="linear"&&config.x.bin?"y":"x";e.total=d3.sum(e.values.map(function(m){return+m.values[axis]}));var counter=0;e.values.forEach(function(v,i){if(config.x.type==="ordinal"||config.x.type==="linear"&&config.x.bin){v.values.y=mark.summarizeY==="percent"?v.values.y/e.total:v.values.y||0;counter+=+v.values.y;v.values.start=e.values[i-1]?counter:v.values.y}else{v.values.x=mark.summarizeX==="percent"?v.values.x/e.total:v.values.x||0;v.values.start=counter;counter+=+v.values.x}})}function makeNest(entries,sublevel){var dom_xs=[];var dom_ys=[];var this_nest=d3.nest();if(config.x.type==="linear"&&config.x.bin||config.y.type==="linear"&&config.y.bin){var xy=config.x.type==="linear"&&config.x.bin?"x":"y";var quant=d3.scale.quantile().domain(d3.extent(entries.map(function(m){return+m[config[xy].column]}))).range(d3.range(+config[xy].bin));entries.forEach(function(e){return e.wc_bin=quant(e[config[xy].column])});this_nest.key(function(d){return quant.invertExtent(d.wc_bin)})}else{this_nest.key(function(d){return mark.per.map(function(m){return d[m]}).join(" ")})}if(sublevel){this_nest.key(function(d){return d[sublevel]});this_nest.sortKeys(function(a,b){return config.x.type==="time"?d3.ascending(new Date(a),new Date(b)):config.x.order?d3.ascending(config.x.order.indexOf(a),config.x.order.indexOf(b)):sublevel===config.color_by&&config.legend.order?d3.ascending(config.legend.order.indexOf(a),config.legend.order.indexOf(b)):config.x.type==="ordinal"||config.y.type==="ordinal"?naturalSorter(a,b):d3.ascending(+a,+b)})}this_nest.rollup(function(r){var obj={raw:r};var y_vals=r.map(function(m){return m[config.y.column]}).sort(d3.ascending);var x_vals=r.map(function(m){return m[config.x.column]}).sort(d3.ascending);obj.x=config.x.type==="ordinal"?r[0][config.x.column]:summarize(x_vals,mark.summarizeX);obj.y=config.y.type==="ordinal"?r[0][config.y.column]:summarize(y_vals,mark.summarizeY);obj.x_q25=config.error_bars&&config.y.type==="ordinal"?d3.quantile(x_vals,.25):obj.x;obj.x_q75=config.error_bars&&config.y.type==="ordinal"?d3.quantile(x_vals,.75):obj.x;obj.y_q25=config.error_bars?d3.quantile(y_vals,.25):obj.y;obj.y_q75=config.error_bars?d3.quantile(y_vals,.75):obj.y;dom_xs.push([obj.x_q25,obj.x_q75,obj.x]);dom_ys.push([obj.y_q25,obj.y_q75,obj.y]);if(mark.summarizeY==="cumulative"){var interm=entries.filter(function(f){return config.x.type==="time"?new Date(f[config.x.column])<=new Date(r[0][config.x.column]):+f[config.x.column]<=+r[0][config.x.column]});if(mark.per.length){interm=interm.filter(function(f){return f[mark.per[0]]===r[0][mark.per[0]]})}var cumul=config.x.type==="time"?interm.length:d3.sum(interm.map(function(m){return+m[config.y.column]||+m[config.y.column]===0?+m[config.y.column]:1}));dom_ys.push([cumul]);obj.y=cumul}if(mark.summarizeX==="cumulative"){var _interm=entries.filter(function(f){return config.y.type==="time"?new Date(f[config.y.column])<=new Date(r[0][config.y.column]):+f[config.y.column]<=+r[0][config.y.column]});if(mark.per.length){_interm=_interm.filter(function(f){return f[mark.per[0]]===r[0][mark.per[0]]})}dom_xs.push([_interm.length]);obj.x=_interm.length}return obj});var test=this_nest.entries(entries);var dom_x=d3.extent(d3.merge(dom_xs));var dom_y=d3.extent(d3.merge(dom_ys));if(sublevel&&mark.type==="bar"&&mark.arrange==="stacked"){test.forEach(calcStartTotal);if(config.x.type==="ordinal"||config.x.type==="linear"&&config.x.bin){dom_y=d3.extent(test.map(function(m){return m.total}))}if(config.y.type==="ordinal"||config.y.type==="linear"&&config.y.bin){dom_x=d3.extent(test.map(function(m){return m.total}))}}else if(sublevel&&mark.type==="bar"&&mark.split){test.forEach(calcStartTotal)}else{var axis=config.x.type==="ordinal"||config.x.type==="linear"&&config.x.bin?"y":"x";test.forEach(function(e){return e.total=e.values[axis]})}if(config.x.sort==="total-ascending"&&config.x.type=="ordinal"||config.y.sort==="total-descending"&&config.y.type=="ordinal"){totalOrder=test.sort(function(a,b){return d3.ascending(a.total,b.total)}).map(function(m){return m.key})}else if(config.x.sort==="total-descending"&&config.x.type=="ordinal"||config.y.sort==="total-ascending"&&config.y.type=="ordinal"){totalOrder=test.sort(function(a,b){return d3.descending(+a.total,+b.total)}).map(function(m){return m.key})}return{nested:test,dom_x:dom_x,dom_y:dom_y}}raw=mark.per&&mark.per.length?raw.filter(function(f){return f[mark.per[0]]}):raw;if(config.x.column){raw=raw.filter(function(f){return f[config.x.column]!==undefined})}if(config.y.column){raw=raw.filter(function(f){return f[config.y.column]!==undefined})}if(config.x.type==="time"){raw=raw.filter(function(f){return f[config.x.column]instanceof Date?f[config.x.column]:dateConvert.parse(f[config.x.column])});raw.forEach(function(e){return e[config.x.column]=e[config.x.column]instanceof Date?e[config.x.column]:dateConvert.parse(e[config.x.column])})}if(config.y.type==="time"){raw=raw.filter(function(f){return f[config.y.column]instanceof Date?f[config.y.column]:dateConvert.parse(f[config.y.column])});raw.forEach(function(e){return e[config.y.column]=e[config.y.column]instanceof Date?e[config.y.column]:dateConvert.parse(e[config.y.column])})}if((config.x.type==="linear"||config.x.type==="log")&&config.x.column){raw=raw.filter(function(f){return mark.summarizeX!=="count"&&mark.summarizeX!=="percent"?+f[config.x.column]||+f[config.x.column]===0:f})}if((config.y.type==="linear"||config.y.type==="log")&&config.y.column){raw=raw.filter(function(f){return mark.summarizeY!=="count"&&mark.summarizeY!=="percent"?+f[config.y.column]||+f[config.y.column]===0:f})}var raw_nest=void 0;if(mark.type==="bar"){raw_nest=mark.arrange!=="stacked"?makeNest(raw,sublevel):makeNest(raw)}else if(mark.summarizeX==="count"||mark.summarizeY==="count"){raw_nest=makeNest(raw)}var raw_dom_x=mark.summarizeX==="cumulative"?[0,raw.length]:config.x.type==="ordinal"?d3.set(raw.map(function(m){return m[config.x.column]})).values().filter(function(f){return f}):mark.split&&mark.arrange!=="stacked"?d3.extent(d3.merge(raw_nest.nested.map(function(m){return m.values.map(function(p){return p.values.raw.length})}))):mark.summarizeX==="count"?d3.extent(raw_nest.nested.map(function(m){return m.values.raw.length})):d3.extent(raw.map(function(m){return+m[config.x.column]}).filter(function(f){return+f||+f===0}));var raw_dom_y=mark.summarizeY==="cumulative"?[0,raw.length]:config.y.type==="ordinal"?d3.set(raw.map(function(m){return m[config.y.column]})).values().filter(function(f){return f}):mark.split&&mark.arrange!=="stacked"?d3.extent(d3.merge(raw_nest.nested.map(function(m){return m.values.map(function(p){return p.values.raw.length})}))):mark.summarizeY==="count"?d3.extent(raw_nest.nested.map(function(m){return m.values.raw.length})):d3.extent(raw.map(function(m){return+m[config.y.column]}).filter(function(f){return+f||+f===0}));var filtered=raw;var filt1_xs=[];var filt1_ys=[];if(this.filters.length){this.filters.forEach(function(e){filtered=filtered.filter(function(d){return e.val==="All"?d:e.val instanceof Array?e.val.indexOf(d[e.col])>-1:d[e.col]===e.val})});if(config.x.behavior==="firstfilter"||config.y.behavior==="firstfilter"){this.filters[0].choices.filter(function(f){return f!=="All"}).forEach(function(e){var perfilter=raw.filter(function(f){return f[_this.filters[0].col]===e});var filt_nested=makeNest(perfilter,sublevel);filt1_xs.push(filt_nested.dom_x);filt1_ys.push(filt_nested.dom_y)})}}if(mark.values){var _loop=function _loop(a){filtered=filtered.filter(function(f){return mark.values[a].indexOf(f[a])>-1})};for(var a in mark.values){_loop(a)}}var filt1_dom_x=d3.extent(d3.merge(filt1_xs));var filt1_dom_y=d3.extent(d3.merge(filt1_ys));var current_nested=makeNest(filtered,sublevel);var flex_dom_x=current_nested.dom_x;var flex_dom_y=current_nested.dom_y;if(mark.type==="bar"){if(config.y.type==="ordinal"&&mark.summarizeX==="count"){config.x.domain=config.x.domain?[0,config.x.domain[1]]:[0,null]}else if(config.x.type==="ordinal"&&mark.summarizeY==="count"){config.y.domain=config.y.domain?[0,config.y.domain[1]]:[0,null]}}var nonall=Boolean(this.filters.length&&this.filters[0].val!=="All"&&this.filters.slice(1).filter(function(f){return f.val==="All"}).length===this.filters.length-1);var pre_x_dom=!this.filters.length?flex_dom_x:x_behavior==="raw"?raw_dom_x:nonall&&x_behavior==="firstfilter"?filt1_dom_x:flex_dom_x;var pre_y_dom=!this.filters.length?flex_dom_y:y_behavior==="raw"?raw_dom_y:nonall&&y_behavior==="firstfilter"?filt1_dom_y:flex_dom_y;var x_dom=config.x_dom?config.x_dom:config.x.type==="ordinal"&&config.x.behavior==="flex"?d3.set(filtered.map(function(m){return m[config.x.column]})).values():config.x.type==="ordinal"?d3.set(raw.map(function(m){return m[config.x.column]})).values():config.x_from0?[0,d3.max(pre_x_dom)]:pre_x_dom;var y_dom=config.y_dom?config.y_dom:config.y.type==="ordinal"&&config.y.behavior==="flex"?d3.set(filtered.map(function(m){return m[config.y.column]})).values():config.y.type==="ordinal"?d3.set(raw.map(function(m){return m[config.y.column]})).values():config.y_from0?[0,d3.max(pre_y_dom)]:pre_y_dom;if(config.x.domain&&(config.x.domain[0]||config.x.domain[0]===0)){x_dom[0]=config.x.domain[0]}if(config.x.domain&&(config.x.domain[1]||config.x.domain[1]===0)){x_dom[1]=config.x.domain[1]}if(config.y.domain&&(config.y.domain[0]||config.y.domain[0]===0)){y_dom[0]=config.y.domain[0]}if(config.y.domain&&(config.y.domain[1]||config.y.domain[1]===0)){y_dom[1]=config.y.domain[1]}if(config.x.type==="ordinal"&&!config.x.order){config.x.order=totalOrder}if(config.y.type==="ordinal"&&!config.y.order){config.y.order=totalOrder}this.current_data=current_nested.nested;this.events.onDatatransform.call(this);return{config:mark,data:current_nested.nested,x_dom:x_dom,y_dom:y_dom}}function updateDataMarks(){this.drawBars(this.marks.filter(function(f){return f.type==="bar"}));this.drawLines(this.marks.filter(function(f){return f.type==="line"}));this.drawPoints(this.marks.filter(function(f){return f.type==="circle"}));this.drawText(this.marks.filter(function(f){return f.type==="text"}));this.marks.supergroups=this.svg.selectAll("g.supergroup")}function xScaleAxis(max_range,domain,type){if(max_range===undefined){max_range=this.plot_width}if(domain===undefined){domain=this.x_dom}if(type===undefined){type=this.config.x.type}var config=this.config;var x=void 0;if(type==="log"){x=d3.scale.log()}else if(type==="ordinal"){x=d3.scale.ordinal()}else if(type==="time"){x=d3.time.scale()}else{x=d3.scale.linear()}x.domain(domain);if(type==="ordinal"){x.rangeBands([0,+max_range],config.padding,config.outer_pad)}else{x.range([0,+max_range]).clamp(Boolean(config.x.clamp))}var xFormat=config.x.format?config.x.format:config.marks.map(function(m){return m.summarizeX==="percent"}).indexOf(true)>-1?"0%":type==="time"?"%x":".0f";var tick_count=Math.max(2,Math.min(max_range/80,8));var xAxis=d3.svg.axis().scale(x).orient(config.x.location).ticks(tick_count).tickFormat(type==="ordinal"?null:type==="time"?d3.time.format(xFormat):d3.format(xFormat)).tickValues(config.x.ticks?config.x.ticks:null).innerTickSize(6).outerTickSize(3);this.svg.select("g.x.axis").attr("class","x axis "+type);this.x=x;this.xAxis=xAxis}function yScaleAxis(max_range,domain,type){if(max_range===undefined){max_range=this.plot_height}if(domain===undefined){domain=this.y_dom}if(type===undefined){type=this.config.y.type}var config=this.config;var y=void 0;if(type==="log"){y=d3.scale.log()}else if(type==="ordinal"){y=d3.scale.ordinal()}else if(type==="time"){y=d3.time.scale()}else{y=d3.scale.linear()}y.domain(domain);if(type==="ordinal"){y.rangeBands([+max_range,0],config.padding,config.outer_pad)}else{y.range([+max_range,0]).clamp(Boolean(config.y_clamp))}var yFormat=config.y.format?config.y.format:config.marks.map(function(m){return m.summarizeY==="percent"}).indexOf(true)>-1?"0%":".0f";var tick_count=Math.max(2,Math.min(max_range/80,8));var yAxis=d3.svg.axis().scale(y).orient("left").ticks(tick_count).tickFormat(type==="ordinal"?null:type==="time"?d3.time.format(yFormat):d3.format(yFormat)).tickValues(config.y.ticks?config.y.ticks:null).innerTickSize(6).outerTickSize(3);this.svg.select("g.y.axis").attr("class","y axis "+type);this.y=y;this.yAxis=yAxis}var chartProto={raw_data:[],config:{}};var chart=Object.create(chartProto,{checkRequired:{value:checkRequired},consolidateData:{value:consolidateData},draw:{value:draw},destroy:{value:destroy},drawArea:{value:drawArea},drawBars:{value:drawBars},drawGridlines:{value:drawGridLines},drawLines:{value:drawLines},drawPoints:{value:drawPoints},drawText:{value:drawText},init:{value:init},layout:{value:layout},makeLegend:{value:makeLegend},resize:{value:resize},setColorScale:{value:setColorScale},setDefaults:{value:setDefaults},setMargins:{value:setMargins},textSize:{value:textSize},transformData:{value:transformData},updateDataMarks:{value:updateDataMarks},xScaleAxis:{value:xScaleAxis},yScaleAxis:{value:yScaleAxis}});var chartCount=0;function createChart(){var element=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var controls=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var thisChart=Object.create(chart);thisChart.div=element;thisChart.config=Object.create(config);thisChart.controls=controls;thisChart.raw_data=[];thisChart.filters=[];thisChart.marks=[];thisChart.wrap=d3.select(thisChart.div).append("div").datum(thisChart);thisChart.events={onInit:function onInit(){},onLayout:function onLayout(){},onPreprocess:function onPreprocess(){},onDatatransform:function onDatatransform(){},onDraw:function onDraw(){},onResize:function onResize(){},onDestroy:function onDestroy(){}};thisChart.on=function(event,callback){var possible_events=["init","layout","preprocess","datatransform","draw","resize","destroy"];if(possible_events.indexOf(event)<0){return}if(callback){thisChart.events["on"+event.charAt(0).toUpperCase()+event.slice(1)]=callback}};chartCount++;thisChart.id=chartCount;return thisChart}function changeOption(option,value,callback){var _this=this;this.targets.forEach(function(e){if(option instanceof Array){option.forEach(function(o){return _this.stringAccessor(e.config,o,value)})}else{_this.stringAccessor(e.config,option,value)}if(callback){callback()}e.draw()})}function checkRequired$1(dataset){if(!dataset[0]||!this.config.inputs){return}var colnames=d3.keys(dataset[0]);this.config.inputs.forEach(function(e,i){if(e.type==="subsetter"&&colnames.indexOf(e.value_col)===-1){throw new Error('Error in settings object: the value "'+e.value_col+'" does not match any column in the provided dataset.')}})}function controlUpdate(){var _this=this;if(this.config.inputs&&this.config.inputs.length&&this.config.inputs[0]){this.config.inputs.forEach(function(e){return _this.makeControlItem(e)})}}function destroy$1(){this.wrap.remove()}function init$1(data){this.data=data;if(!this.config.builder){this.checkRequired(this.data)}this.layout()}function layout$1(){this.wrap.selectAll("*").remove();this.ready=true;this.controlUpdate()}function makeControlItem(control){var control_wrap=this.wrap.append("div").attr("class","control-group").classed("inline",control.inline).datum(control);var ctrl_label=control_wrap.append("span").attr("class","control-label").text(control.label);if(control.required){ctrl_label.append("span").attr("class","label label-required").text("Required")}control_wrap.append("span").attr("class","span-description").text(control.description);if(control.type==="text"){this.makeTextControl(control,control_wrap)}else if(control.type==="number"){this.makeNumberControl(control,control_wrap)}else if(control.type==="list"){this.makeListControl(control,control_wrap)}else if(control.type==="dropdown"){this.makeDropdownControl(control,control_wrap)}else if(control.type==="btngroup"){this.makeBtnGroupControl(control,control_wrap)}else if(control.type==="checkbox"){this.makeCheckboxControl(control,control_wrap)}else if(control.type==="radio"){this.makeRadioControl(control,control_wrap)}else if(control.type==="subsetter"){this.makeSubsetterControl(control,control_wrap)}else{throw new Error('Each control must have a type! Choose from: "text", "number", "list", "dropdown", "btngroup", "checkbox", "radio", "subsetter"')}}function makeBtnGroupControl(control,control_wrap){var _this=this;var option_data=control.values?control.values:d3.keys(this.data[0]);var btn_wrap=control_wrap.append("div").attr("class","btn-group");var changers=btn_wrap.selectAll("button").data(option_data).enter().append("button").attr("class","btn btn-default btn-sm").text(function(d){return d}).classed("btn-primary",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)===d});changers.on("click",function(d){changers.each(function(e){d3.select(this).classed("btn-primary",e===d)});_this.changeOption(control.option,d,control.callback)})}function makeCheckboxControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","checkbox").attr("class","changer").datum(control).property("checked",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("checked");_this.changeOption(d.option,value,control.callback)})}function makeDropdownControl(control,control_wrap){var _this=this;var mainOption=control.option||control.options[0];var changer=control_wrap.append("select").attr("class","changer").attr("multiple",control.multiple?true:null).datum(control);var opt_values=control.values&&control.values instanceof Array?control.values:control.values?d3.set(this.data.map(function(m){return m[_this.targets[0].config[control.values]]})).values():d3.keys(this.data[0]);if(!control.require||control.none){opt_values.unshift("None")}var options=changer.selectAll("option").data(opt_values).enter().append("option").text(function(d){return d}).property("selected",function(d){return _this.stringAccessor(_this.targets[0].config,mainOption)===d});changer.on("change",function(d){var value=changer.property("value")==="None"?null:changer.property("value");if(control.multiple){value=options.filter(function(f){return d3.select(this).property("selected")})[0].map(function(m){return d3.select(m).property("value")}).filter(function(f){return f!=="None"})}if(control.options){_this.changeOption(control.options,value,control.callback)}else{_this.changeOption(control.option,value,control.callback)}});return changer}function makeListControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","text").attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("value")?changer.property("value").split(",").map(function(m){return m.trim()}):null;_this.changeOption(control.option,value,control.callback)})}function makeNumberControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","number").attr("min",control.min!==undefined?control.min:0).attr("max",control.max).attr("step",control.step||1).attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=+changer.property("value");_this.changeOption(control.option,value,control.callback)})}function makeRadioControl(control,control_wrap){var _this=this;var changers=control_wrap.selectAll("label").data(control.values||d3.keys(this.data[0])).enter().append("label").attr("class","radio").text(function(d,i){return control.relabels?control.relabels[i]:d}).append("input").attr("type","radio").attr("class","changer").attr("name",control.option.replace(".","-")+"-"+this.targets[0].id).property("value",function(d){return d}).property("checked",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)===d});changers.on("change",function(d){var value=null;changers.each(function(c){if(d3.select(this).property("checked")){value=d3.select(this).property("value")==="none"?null:c}});_this.changeOption(control.option,value,control.callback)})}function makeSubsetterControl(control,control_wrap){var targets=this.targets;var changer=control_wrap.append("select").attr("class","changer").attr("multiple",control.multiple?true:null).datum(control);var option_data=control.values?control.values:d3.set(this.data.map(function(m){return m[control.value_col]}).filter(function(f){return f})).values();option_data.sort(naturalSorter);control.start=control.start?control.start:control.loose?option_data[0]:null;if(!control.multiple&&!control.start){option_data.unshift("All")}control.loose=!control.loose&&control.start?true:control.loose;var options=changer.selectAll("option").data(option_data).enter().append("option").text(function(d){return d}).property("selected",function(d){return d===control.start});targets.forEach(function(e){var match=e.filters.slice().map(function(m){return m.col===control.value_col}).indexOf(true);if(match>-1){e.filters[match]={col:control.value_col,val:control.start?control.start:"All",choices:option_data,loose:control.loose}}else{e.filters.push({col:control.value_col,val:control.start?control.start:"All",choices:option_data,loose:control.loose})}});function setSubsetter(target,obj){var match=-1;target.filters.forEach(function(e,i){if(e.col===obj.col){match=i}});if(match>-1){target.filters[match]=obj}}changer.on("change",function(d){if(control.multiple){var values=options.filter(function(f){return d3.select(this).property("selected")})[0].map(function(m){return d3.select(m).property("text")});var new_filter={col:control.value_col,val:values,choices:option_data,loose:control.loose};targets.forEach(function(e){setSubsetter(e,new_filter);if(control.callback){control.callback()}e.draw()})}else{var value=d3.select(this).select("option:checked").property("text");var _new_filter={col:control.value_col,val:value,choices:option_data,loose:control.loose};targets.forEach(function(e){setSubsetter(e,_new_filter);if(control.callback){control.callback()}e.draw()})}})}function makeTextControl(control,control_wrap){var _this=this;var changer=control_wrap.append("input").attr("type","text").attr("class","changer").datum(control).property("value",function(d){return _this.stringAccessor(_this.targets[0].config,control.option)});changer.on("change",function(d){var value=changer.property("value");_this.changeOption(control.option,value,control.callback)})}function stringAccessor(o,s,v){s=s.replace(/\[(\w+)\]/g,".$1");s=s.replace(/^\./,"");var a=s.split(".");for(var i=0,n=a.length;i0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var thisControls=Object.create(controls);thisControls.div=element;thisControls.config=Object.create(config);thisControls.config.inputs=thisControls.config.inputs||[];thisControls.targets=[];if(config.location==="bottom"){thisControls.wrap=d3.select(element).append("div").attr("class","wc-controls")}else{thisControls.wrap=d3.select(element).insert("div",":first-child").attr("class","wc-controls")}thisControls.wrap.datum(thisControls);return thisControls}var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};function clone(obj){var copy=void 0;if("object"!=(typeof obj==="undefined"?"undefined":_typeof(obj))||null==obj)return obj;if(obj instanceof Date){copy=new Date;copy.setTime(obj.getTime());return copy}if(obj instanceof Array){copy=[];for(var i=0,len=obj.length;i-1:filter.val===d[filter.col]});return match}):clone(this.data.raw)}function applySearchTerm(){var _this=this;this.data.searched=this.data.filtered.filter(function(d){var match=false;Object.keys(d).filter(function(key){return _this.config.cols.indexOf(key)>-1}).forEach(function(var_name){if(match===false){var cellText=""+d[var_name];match=cellText.toLowerCase().indexOf(_this.searchable.searchTerm)>-1}});return match})}if(Array.prototype.equals)console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");Array.prototype.equals=function(array){if(!array)return false;if(this.length!=array.length)return false;for(var i=0,l=this.length;i=Math.max(widths.top,widths.bottom)&&this.config.layout==="vertical"){this.config.layout="horizontal";this.wrap.style("display","table").selectAll(".table-top,.table-bottom").style("display","block").selectAll(".interactivity").style({display:"inline-block",float:function float(){return d3.select(this).classed("searchable-container")||d3.select(this).classed("pagination-container")?"right":null},clear:null})}this.events.onDraw.call(this)}function layout$2(){var context=this;this.searchable.wrap=this.wrap.select(".table-top").append("div").classed("interactivity searchable-container",true).classed("hidden",!this.config.searchable);this.searchable.wrap.append("div").classed("search",true);this.searchable.wrap.select(".search").append("input").classed("search-box",true).attr("placeholder","Search").on("input",function(){context.searchable.searchTerm=this.value.toLowerCase()||null;context.config.activePage=0;context.config.startIndex=context.config.activePage*context.config.nRowsPerPage;context.config.endIndex=context.config.startIndex+context.config.nRowsPerPage;context.draw()});this.searchable.wrap.select(".search").append("span").classed("nNrecords",true)}function searchable(){return{layout:layout$2}}function layout$3(){var _this=this;this.exportable.wrap=this.wrap.select(".table-bottom").append("div").classed("interactivity exportable-container",true).classed("hidden",!this.config.exportable);this.exportable.wrap.append("span").text("Export:");if(this.config.exports&&this.config.exports.length)this.config.exports.forEach(function(fmt){_this.exportable.wrap.append("a").classed("wc-button export",true).attr({id:fmt}).text(fmt.toUpperCase())})}function csv(data){var _this=this;var CSVarray=[];data.forEach(function(d,i){if(i===0){var headers=_this.config.headers.map(function(header){return'"'+header.replace(/"/g,'""')+'"'});CSVarray.push(headers)}var row=_this.config.cols.map(function(col){var value=d[col];if(typeof value==="string")value=value.replace(/"/g,'""');return'"'+value+'"'});CSVarray.push(row)});var CSV=new Blob([CSVarray.join("\n")],{type:"text/csv;charset=utf-8;"}),fileName="webchartsTableExport_"+d3.time.format("%Y-%m-%dT%H-%M-%S")(new Date)+".csv",link=this.wrap.select(".export#csv");if(navigator.msSaveBlob){link.style({cursor:"pointer","text-decoration":"underline",color:"blue"});link.on("click",function(){navigator.msSaveBlob(CSV,fileName)})}else{if(link.node().download!==undefined){var url=URL.createObjectURL(CSV);link.node().setAttribute("href",url);link.node().setAttribute("download",fileName)}}}function xlsx(data){var _this=this;var sheetName="Selected Data",options={bookType:"xlsx",bookSST:true,type:"binary"},arrayOfArrays=data.map(function(d){return Object.keys(d).filter(function(key){return _this.config.cols.indexOf(key)>-1}).map(function(key){return d[key]})}),workbook={SheetNames:[sheetName],Sheets:{}},cols=[];workbook.Sheets[sheetName]=XLSX.utils.aoa_to_sheet([this.config.headers].concat(arrayOfArrays));workbook.Sheets[sheetName]["!autofilter"]={ref:"A1:"+String.fromCharCode(64+this.config.cols.length)+(data.length+1)};this.table.selectAll("thead tr th").each(function(){cols.push({wpx:this.offsetWidth})});workbook.Sheets[sheetName]["!cols"]=cols;var xlsx=XLSX.write(workbook,options),s2ab=function s2ab(s){var buffer=new ArrayBuffer(s.length),view=new Uint8Array(buffer);for(var i=0;i!==s.length;++i){view[i]=s.charCodeAt(i)&255}return buffer};var blob=new Blob([s2ab(xlsx)],{type:"application/octet-stream;"}),fileName="webchartsTableExport_"+d3.time.format("%Y-%m-%dT%H-%M-%S")(new Date)+".xlsx",link=this.wrap.select(".export#xlsx");if(navigator.msSaveBlob){link.style({cursor:"pointer","text-decoration":"underline",color:"blue"});link.on("click",function(){navigator.msSaveBlob(blob,fileName)})}else{if(link.node().download!==undefined){var url=URL.createObjectURL(blob);link.node().setAttribute("href",url);link.node().setAttribute("download",fileName)}}}var exports$1={csv:csv,xlsx:xlsx};function exportable(){return{layout:layout$3,exports:exports$1}}function layout$4(){this.sortable.wrap=this.wrap.select(".table-top").append("div").classed("interactivity sortable-container",true).classed("hidden",!this.config.sortable);this.sortable.wrap.append("div").classed("instruction",true).text("Click column headers to sort.")}function onClick(th,header){var context=this,selection=d3.select(th),col=this.config.cols[this.config.headers.indexOf(header)];var sortItem=this.sortable.order.filter(function(item){return item.col===col})[0];if(!sortItem){sortItem={col:col,direction:"ascending",wrap:this.sortable.wrap.append("div").datum({key:col}).classed("wc-button sort-box",true).text(header)};sortItem.wrap.append("span").classed("sort-direction",true).html("↓");sortItem.wrap.append("span").classed("remove-sort",true).html("❌");this.sortable.order.push(sortItem)}else{sortItem.direction=sortItem.direction==="ascending"?"descending":"ascending";sortItem.wrap.select("span.sort-direction").html(sortItem.direction==="ascending"?"↓":"↑")}this.sortable.wrap.select(".instruction").classed("hidden",true);this.sortable.order.forEach(function(item,i){item.wrap.on("click",function(d){d3.select(this).remove();context.sortable.order.splice(context.sortable.order.map(function(d){return d.col}).indexOf(d.key),1);context.sortable.wrap.select(".instruction").classed("hidden",context.sortable.order.length);context.draw()})});this.draw()}function sortData(data){var _this=this;data=data.sort(function(a,b){var order=0;_this.sortable.order.forEach(function(item){var aCell=a[item.col],bCell=b[item.col];if(order===0){if(item.direction==="ascending"&&aCellbCell)order=-1;else if(item.direction==="ascending"&&aCell>bCell||item.direction==="descending"&&aCell=_this.config.nPageLinksDisplayed:_this.config.activePage>=_this.config.nPages-_this.config.nPageLinksDisplayed?i<_this.config.nPages-_this.config.nPageLinksDisplayed:i<_this.config.activePage-(Math.ceil(_this.config.nPageLinksDisplayed/2)-1)||_this.config.activePage+_this.config.nPageLinksDisplayed/2=this.config.nPages)next=this.config.nPages-1;this.pagination.wrap.insert("span",":first-child").classed("dot-dot-dot",true).text("...").classed("hidden",this.config.activePage=Math.max(this.config.nPageLinksDisplayed,this.config.nPages-this.config.nPageLinksDisplayed)||this.config.nPages<=this.config.nPageLinksDisplayed);this.pagination.next=this.pagination.wrap.append("a").classed("wc-button arrow-link right",true).classed("hidden",this.config.activePage==this.config.nPages-1||this.config.nPages==0).attr({rel:next}).text(">");this.pagination.doubleNext=this.pagination.wrap.append("a").classed("wc-button arrow-link right double",true).classed("hidden",this.config.activePage==this.config.nPages-1||this.config.nPages==0).attr({rel:this.config.nPages-1}).text(">>");this.pagination.arrows=this.pagination.wrap.selectAll("a.arrow-link");this.pagination.doubleArrows=this.pagination.wrap.selectAll("a.double-arrow-link")}function addPagination(data){var context=this;this.config.nRows=data.length;this.config.nPages=Math.ceil(this.config.nRows/this.config.nRowsPerPage);this.config.paginationHidden=this.config.nPages===1;this.pagination.wrap.classed("hidden",this.config.paginationHidden);addLinks.call(this);this.pagination.links.on("click",function(){context.config.activePage=+d3.select(this).attr("rel");updatePagination.call(context)});addArrows.call(this);this.pagination.arrows.on("click",function(){if(context.config.activePage!==+d3.select(this).attr("rel")){context.config.activePage=+d3.select(this).attr("rel");context.pagination.prev.attr("rel",context.config.activePage>0?context.config.activePage-1:0);context.pagination.next.attr("rel",context.config.activePage1&&arguments[1]!==undefined?arguments[1]:false;if(d3.select(this.div).select(".loader").empty()){d3.select(this.div).insert("div",":first-child").attr("class","loader").selectAll(".blockG").data(d3.range(8)).enter().append("div").attr("class",function(d){return"blockG rotate"+(d+1)})}this.setDefaults.call(this,data[0]);this.wrap.classed("wc-chart",true).classed("wc-table",this.config.applyCSS);this.data={raw:data};this.searchable=searchable.call(this);this.sortable=sortable.call(this);this.pagination=pagination.call(this);this.exportable=exportable.call(this);var startup=function startup(data){if(_this.controls){_this.controls.targets.push(_this);if(!_this.controls.ready){_this.controls.init(_this.data.raw)}else{_this.controls.layout()}}var visible=d3.select(_this.div).property("offsetWidth")>0||test;if(!visible){console.warn("The table cannot be initialized inside an element with 0 width. The table will be initialized as soon as the container element is given a width > 0.");var onVisible=setInterval(function(i){var visible_now=d3.select(_this.div).property("offsetWidth")>0;if(visible_now){_this.layout();_this.wrap.datum(_this);_this.draw();clearInterval(onVisible)}},500)}else{_this.layout();_this.wrap.datum(_this);_this.draw()}};this.events.onInit.call(this);if(this.data.raw.length){this.checkRequired(this.data.raw)}startup(data);return this}function layout$6(){d3.select(this.div).select(".loader").remove();this.wrap.append("div").classed("table-top",true);this.searchable.layout.call(this);this.sortable.layout.call(this);this.table=this.wrap.append("table").classed("table",this.config.bootstrap);this.thead=this.table.append("thead");this.thead.append("tr");this.tbody=this.table.append("tbody");this.wrap.append("div").classed("table-bottom",true);this.pagination.layout.call(this);this.exportable.layout.call(this);this.events.onLayout.call(this)}function destroy$2(){var destroyControls=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;this.events.onDestroy.call(this);if(destroyControls&&this.controls){this.controls.destroy()}this.wrap.remove()}function setDefault(setting){var _default_=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;this.config[setting]=this.config[setting]!==undefined?this.config[setting]:_default_}function setDefaults$1(firstItem){if(this.config.cols instanceof Array&&this.config.headers instanceof Array){if(this.config.cols.length===0)delete this.config.cols;if(this.config.headers.length===0||this.config.headers.length!==this.config.cols.length)delete this.config.headers}this.config.cols=this.config.cols||d3.keys(firstItem);this.config.headers=this.config.headers||this.config.cols;this.config.layout="horizontal";setDefault.call(this,"searchable");setDefault.call(this,"exportable");setDefault.call(this,"exports",["csv"]);setDefault.call(this,"sortable");setDefault.call(this,"pagination");setDefault.call(this,"nRowsPerPage",10);setDefault.call(this,"nPageLinksDisplayed",5);setDefault.call(this,"applyCSS")}function transformData$1(processed_data){var _this=this;this.data.processed=this.transformData(this.wrap.datum);if(!data){return}this.config.cols=this.config.cols||d3.keys(data[0]);this.config.headers=this.config.headers||this.config.cols;if(this.config.keep){this.config.keep.forEach(function(e){if(_this.config.cols.indexOf(e)===-1){_this.config.cols.unshift(e)}})}var filtered=data;if(this.filters.length){this.filters.forEach(function(e){var is_array=e.val instanceof Array;filtered=filtered.filter(function(d){if(is_array){return e.val.indexOf(d[e.col])!==-1}else{return e.val!=="All"?d[e.col]===e.val:d}})})}var slimmed=d3.nest().key(function(d){if(_this.config.row_per){return _this.config.row_per.map(function(m){return d[m]}).join(" ")}else{return d}}).rollup(function(r){if(_this.config.dataManipulate){r=_this.config.dataManipulate(r)}var nuarr=r.map(function(m){var arr=[];for(var x in m){arr.push({col:x,text:m[x]})}arr.sort(function(a,b){return _this.config.cols.indexOf(a.col)-_this.config.cols.indexOf(b.col)});return{cells:arr,raw:m}});return nuarr}).entries(filtered);this.data.current=slimmed.length?slimmed:[{key:null,values:[]}];this.pagination.wrap.selectAll("*").remove();this.events.onDatatransform.call(this);if(config.row_per){var rev_order=config.row_per.slice(0).reverse();rev_order.forEach(function(e){tbodies.sort(function(a,b){return a.values[0].raw[e]-b.values[0].raw[e]})})}if(config.row_per){rows.filter(function(f,i){return i>0}).selectAll("td").filter(function(f){return config.row_per.indexOf(f.col)>-1}).text("")}return this.data.current}var table=Object.create(chart,{draw:{value:draw$1},init:{value:init$2},layout:{value:layout$6},setDefaults:{value:setDefaults$1},transformData:{value:transformData$1},destroy:{value:destroy$2}});function createTable(){var element=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"body";var config=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var controls=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var thisTable=Object.create(table);thisTable.div=element;thisTable.config=Object.create(config);thisTable.controls=controls;thisTable.filters=[];thisTable.required_cols=[];thisTable.wrap=d3.select(thisTable.div).append("div");thisTable.events={onInit:function onInit(){},onLayout:function onLayout(){},onPreprocess:function onPreprocess(){},onDatatransform:function onDatatransform(){},onDraw:function onDraw(){},onResize:function onResize(){},onDestroy:function onDestroy(){}};thisTable.on=function(event,callback){var possible_events=["init","layout","preprocess","datatransform","draw","resize","destroy"];if(possible_events.indexOf(event)<0){return}if(callback){thisTable.events["on"+event.charAt(0).toUpperCase()+event.slice(1)]=callback}};return thisTable}function multiply(chart,data,split_by,order){var test=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;var config=chart.config;var wrap=chart.wrap.classed("wc-layout wc-small-multiples",true).classed("wc-chart",false);var master_legend=wrap.append("ul").attr("class","legend");chart.multiples=[];function goAhead(data){var split_vals=d3.set(data.map(function(m){return m[split_by]})).values().filter(function(f){return f});if(order){split_vals=split_vals.sort(function(a,b){return d3.ascending(order.indexOf(a),order.indexOf(b))})}split_vals.forEach(function(e){var mchart=createChart(chart.wrap.node(),config,chart.controls);chart.multiples.push(mchart);mchart.parent=chart;mchart.events=chart.events;mchart.legend=master_legend;mchart.filters.unshift({col:split_by,val:e,choices:split_vals});mchart.wrap.insert("span","svg").attr("class","wc-chart-title").text(e);mchart.init(data,test)})}goAhead(data)}function getValType(data,variable){var var_vals=d3.set(data.map(function(m){return m[variable]})).values();var vals_numbers=var_vals.filter(function(f){return+f||+f===0});if(var_vals.length===vals_numbers.length&&var_vals.length>4){return"continuous"}else{return"categorical"}}function lengthenRaw(data,columns){var my_data=[];data.forEach(function(e){columns.forEach(function(g){var obj=Object.create(e);obj.wc_category=g;obj.wc_value=e[g];my_data.push(obj)})});return my_data}var dataOps={getValType:getValType,lengthenRaw:lengthenRaw,naturalSorter:naturalSorter,summarize:summarize};var index={version:version,createChart:createChart,createControls:createControls,createTable:createTable,multiply:multiply,dataOps:dataOps};return index});
\ No newline at end of file
diff --git a/css/webcharts.css b/css/webcharts.css
index 1caf00e..4232c46 100644
--- a/css/webcharts.css
+++ b/css/webcharts.css
@@ -75,7 +75,6 @@
font-size: .9em;
padding: 0;
margin: 0;
- display: inline-block;
}
*[class*="wc-"] .legend .legend-title {
diff --git a/css/webcharts.min.css b/css/webcharts.min.css
index 4a2969b..086b535 100644
--- a/css/webcharts.min.css
+++ b/css/webcharts.min.css
@@ -1 +1 @@
-@import url(//fonts.googleapis.com/css?family=Open+Sans:400,300);div.wc-layout.wc-small-multiples::after{content:"";clear:both;display:block}.wc-layout.wc-small-multiples>.wc-chart{float:left;padding:0 2em 2em 0}.wc-layout.wc-small-multiples>.wc-chart>.wc-chart-title{display:block;font-weight:700;text-align:center}.wc-small-multiples .wc-chart>.legend{display:none}.wc-chart{position:relative;font-family:'Open Sans',Helvetica,Arial,sans-serif}.wc-chart line,.wc-chart rect{shape-rendering:crispEdges}.wc-chart.brushable .overlay{cursor:crosshair}.wc-chart rect.background{display:none}.wc-chart rect.extent{fill:#ccc;fill-opacity:.4;shape-rendering:crispEdges}.wc-chart .axis path.domain{fill:none;stroke:#ccc;shape-rendering:crispEdges}.wc-chart .axis .tick line{stroke:#eee;shape-rendering:crispEdges}.wc-chart .axis .tick text{font-size:.9em}.wc-chart .axis .axis-title{fill:#555}[class*=wc-] .legend{font-size:.9em;padding:0;margin:0;display:inline-block}[class*=wc-] .legend .legend-title{font-weight:700;margin-right:1em}[class*=wc-] .legend .legend-item{display:inline-block;margin-right:1em}[class*=wc-] .legend .legend-item .legend-color-block{position:relative;top:.2em;right:.25em;display:inline-block}[class*=wc-] .legend .legend-item .legend-mark-text{font-weight:700;margin-right:.5em}.wc-chart .ordinal.axis .tick line,.wc-chart .ordinal.axis path{display:none}.wc-chart.gridlines .ordinal.axis .tick line{display:block}.wc-controls{display:block;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:.9em;margin-bottom:10px}.wc-controls:empty{display:none}.intro>.wc-controls{display:block}.wc-controls .control-group{display:inline-table;max-width:100%;margin:0 1em 1em 0}.wc-controls.bottom .control-group{display:inline-table}.wc-controls .control-group .wc-control-label{display:block}.wc-controls .control-group.inline .wc-control-label{display:inline;margin-right:.5em}.wc-controls .control-group.inline .changer{display:inline;margin-top:0}.wc-controls .control-group .wc-control-label+.changer{margin-top:2px}.wc-controls .control-group .wc-control-label.inline{display:inline;margin-right:.5em}.wc-controls .control-group .wc-control-label .label-required{color:#de2d26;padding:0 .25em;border:1px solid;margin-left:.5em}.wc-controls .span-description{display:block;font-size:.75em;color:#777;margin-bottom:3px}.wc-controls .span-description:empty{display:none}.wc-controls .span-description.standout{font-style:italic;color:#d9534f}.wc-controls .control-group label.filter-values,.wc-controls .control-group label.radio{display:inline-block;cursor:pointer;font-weight:400;font-size:.9em;padding:0;margin:5px 10px 0 0}.wc-controls .inline{display:inline}.wc-controls .control-group input[type=text],.wc-controls select{display:block;width:auto;max-width:100%;padding:0 2px;height:auto;border-radius:0}.wc-controls .control-group input[type=number]{width:70px;text-align:right;max-width:100%}.wc-controls .control-group input[type=checkbox],.wc-controls .control-group input[type=radio]{cursor:pointer;position:relative;top:.1em;float:none;margin:0}.wc-controls .control-group input[type=radio]{vertical-align:bottom;margin-left:.25em}.wc-controls .control-group input.inline{margin:0 2px 2px 0}.wc-controls .control-group .changer+.changer{margin-top:2px}.wc-controls .subsetter-ui{position:relative;display:inline-block;max-width:100%;padding:3px;border:1px dashed #888;margin:5px 5px 0 0}.wc-controls .subsetter-ui .remove-btn{cursor:pointer;position:absolute;top:2px;right:2px}.wc-table{display:block}.wc-table .hidden{display:none!important}.wc-table .invisible{visibility:hidden!important}.wc-table>*{display:block}.wc-table .interactivity{display:inline-block;vertical-align:middle;margin:10px 0;padding:0}.wc-table .interactivity .wc-button{display:inline-block;border:2px solid gray;border-radius:4px;padding:2px 8px;margin:0 2px;cursor:pointer;background:#fff;color:#000}.wc-table .interactivity .wc-button:hover{background:#000;color:#fff}.wc-table .searchable-container{float:right;overflow:hidden}.wc-table .searchable-container input{margin:0 10px 0 0;padding:4px}.wc-table .sortable-container{margin-right:10px}.wc-table .sortable-container .instruction{margin-top:4px}.wc-table .sortable-container .sort-box{cursor:default;padding:2px 4px}.wc-table .sortable-container .sort-direction{font-weight:700;margin:3px}.wc-table .sortable-container .sort-box .remove-sort{font-weight:700;float:right;border:1px solid gray;margin-top:3px;padding:2px 3px;font-size:8px;background:#fff;color:red}.wc-table .sortable-container .sort-box .remove-sort:hover{cursor:pointer;background:red;color:#fff}.wc-table table{font-size:.9em;border-collapse:collapse}.wc-table table thead tr th{cursor:pointer;padding:2px 5px;border-bottom:2px solid #000;text-align:left}.wc-table table tbody tr:nth-child(even){background:#eee}.wc-table table tbody tr:hover{background:#ccc}.wc-table table tbody tr td{padding:2px 5px}.wc-table table tbody tr:last-child{border-bottom:1px solid #000}.wc-table table tbody tr.no-data td{color:red;font-weight:700}.wc-table .pagination-container{float:right}.wc-table .pagination-container a{text-decoration:none}.wc-table .pagination-container a:not(.active){border:none}.wc-table .exportable-container{float:left}.wc-table .exportable-container a{text-decoration:none}.loader{position:relative;width:20px;height:25px}.blockG{position:absolute;background-color:#eee;width:3px;height:8px;-moz-border-radius:4px 4px 0 0;-moz-transform:scale(.4);-moz-animation-name:fadeG;-moz-animation-duration:.48s;-moz-animation-iteration-count:infinite;-moz-animation-direction:linear;-webkit-border-radius:4px 4px 0 0;-webkit-transform:scale(.4);-webkit-animation-name:fadeG;-webkit-animation-duration:.48s;-webkit-animation-iteration-count:infinite;-webkit-animation-direction:linear;-ms-border-radius:4px 4px 0 0;-ms-transform:scale(.4);-ms-animation-name:fadeG;-ms-animation-duration:.48s;-ms-animation-iteration-count:infinite;-ms-animation-direction:linear;-o-border-radius:4px 4px 0 0;-o-transform:scale(.4);-o-animation-name:fadeG;-o-animation-duration:.48s;-o-animation-iteration-count:infinite;-o-animation-direction:linear;border-radius:4px 4px 0 0;transform:scale(.4);animation-name:fadeG;animation-duration:.48s;animation-iteration-count:infinite;animation-direction:linear}.rotate1{left:0;top:9px;-moz-animation-delay:.18s;-moz-transform:rotate(-90deg);-webkit-animation-delay:.18s;-webkit-transform:rotate(-90deg);-ms-animation-delay:.18s;-ms-transform:rotate(-90deg);-o-animation-delay:.18s;-o-transform:rotate(-90deg);animation-delay:.18s;transform:rotate(-90deg)}.rotate2{left:3px;top:3px;-moz-animation-delay:.24s;-moz-transform:rotate(-45deg);-webkit-animation-delay:.24s;-webkit-transform:rotate(-45deg);-ms-animation-delay:.24s;-ms-transform:rotate(-45deg);-o-animation-delay:.24s;-o-transform:rotate(-45deg);animation-delay:.24s;transform:rotate(-45deg)}.rotate3{left:8px;top:1px;-moz-animation-delay:.3s;-moz-transform:rotate(0);-webkit-animation-delay:.3s;-webkit-transform:rotate(0);-ms-animation-delay:.3s;-ms-transform:rotate(0);-o-animation-delay:.3s;-o-transform:rotate(0);animation-delay:.3s;transform:rotate(0)}.rotate4{right:3px;top:3px;-moz-animation-delay:.36s;-moz-transform:rotate(45deg);-webkit-animation-delay:.36s;-webkit-transform:rotate(45deg);-ms-animation-delay:.36s;-ms-transform:rotate(45deg);-o-animation-delay:.36s;-o-transform:rotate(45deg);animation-delay:.36s;transform:rotate(45deg)}.rotate5{right:0;top:9px;-moz-animation-delay:.42000000000000004s;-moz-transform:rotate(90deg);-webkit-animation-delay:.42000000000000004s;-webkit-transform:rotate(90deg);-ms-animation-delay:.42000000000000004s;-ms-transform:rotate(90deg);-o-animation-delay:.42000000000000004s;-o-transform:rotate(90deg);animation-delay:.42000000000000004s;transform:rotate(90deg)}.rotate6{right:3px;bottom:2px;-moz-animation-delay:.48s;-moz-transform:rotate(135deg);-webkit-animation-delay:.48s;-webkit-transform:rotate(135deg);-ms-animation-delay:.48s;-ms-transform:rotate(135deg);-o-animation-delay:.48s;-o-transform:rotate(135deg);animation-delay:.48s;transform:rotate(135deg)}.rotate7{bottom:0;left:8px;-moz-animation-delay:.5399999999999999s;-moz-transform:rotate(180deg);-webkit-animation-delay:.5399999999999999s;-webkit-transform:rotate(180deg);-ms-animation-delay:.5399999999999999s;-ms-transform:rotate(180deg);-o-animation-delay:.5399999999999999s;-o-transform:rotate(180deg);animation-delay:.5399999999999999s;transform:rotate(180deg)}.rotate8{left:3px;bottom:2px;-moz-animation-delay:.6s;-moz-transform:rotate(-135deg);-webkit-animation-delay:.6s;-webkit-transform:rotate(-135deg);-ms-animation-delay:.6s;-ms-transform:rotate(-135deg);-o-animation-delay:.6s;-o-transform:rotate(-135deg);animation-delay:.6s;transform:rotate(-135deg)}@-moz-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-webkit-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-ms-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-o-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}
\ No newline at end of file
+@import url(//fonts.googleapis.com/css?family=Open+Sans:400,300);div.wc-layout.wc-small-multiples::after{content:"";clear:both;display:block}.wc-layout.wc-small-multiples>.wc-chart{float:left;padding:0 2em 2em 0}.wc-layout.wc-small-multiples>.wc-chart>.wc-chart-title{display:block;font-weight:700;text-align:center}.wc-small-multiples .wc-chart>.legend{display:none}.wc-chart{position:relative;font-family:'Open Sans',Helvetica,Arial,sans-serif}.wc-chart line,.wc-chart rect{shape-rendering:crispEdges}.wc-chart.brushable .overlay{cursor:crosshair}.wc-chart rect.background{display:none}.wc-chart rect.extent{fill:#ccc;fill-opacity:.4;shape-rendering:crispEdges}.wc-chart .axis path.domain{fill:none;stroke:#ccc;shape-rendering:crispEdges}.wc-chart .axis .tick line{stroke:#eee;shape-rendering:crispEdges}.wc-chart .axis .tick text{font-size:.9em}.wc-chart .axis .axis-title{fill:#555}[class*=wc-] .legend{font-size:.9em;padding:0;margin:0}[class*=wc-] .legend .legend-title{font-weight:700;margin-right:1em}[class*=wc-] .legend .legend-item{display:inline-block;margin-right:1em}[class*=wc-] .legend .legend-item .legend-color-block{position:relative;top:.2em;right:.25em;display:inline-block}[class*=wc-] .legend .legend-item .legend-mark-text{font-weight:700;margin-right:.5em}.wc-chart .ordinal.axis .tick line,.wc-chart .ordinal.axis path{display:none}.wc-chart.gridlines .ordinal.axis .tick line{display:block}.wc-controls{display:block;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:.9em;margin-bottom:10px}.wc-controls:empty{display:none}.intro>.wc-controls{display:block}.wc-controls .control-group{display:inline-table;max-width:100%;margin:0 1em 1em 0}.wc-controls.bottom .control-group{display:inline-table}.wc-controls .control-group .wc-control-label{display:block}.wc-controls .control-group.inline .wc-control-label{display:inline;margin-right:.5em}.wc-controls .control-group.inline .changer{display:inline;margin-top:0}.wc-controls .control-group .wc-control-label+.changer{margin-top:2px}.wc-controls .control-group .wc-control-label.inline{display:inline;margin-right:.5em}.wc-controls .control-group .wc-control-label .label-required{color:#de2d26;padding:0 .25em;border:1px solid;margin-left:.5em}.wc-controls .span-description{display:block;font-size:.75em;color:#777;margin-bottom:3px}.wc-controls .span-description:empty{display:none}.wc-controls .span-description.standout{font-style:italic;color:#d9534f}.wc-controls .control-group label.filter-values,.wc-controls .control-group label.radio{display:inline-block;cursor:pointer;font-weight:400;font-size:.9em;padding:0;margin:5px 10px 0 0}.wc-controls .inline{display:inline}.wc-controls .control-group input[type=text],.wc-controls select{display:block;width:auto;max-width:100%;padding:0 2px;height:auto;border-radius:0}.wc-controls .control-group input[type=number]{width:70px;text-align:right;max-width:100%}.wc-controls .control-group input[type=checkbox],.wc-controls .control-group input[type=radio]{cursor:pointer;position:relative;top:.1em;float:none;margin:0}.wc-controls .control-group input[type=radio]{vertical-align:bottom;margin-left:.25em}.wc-controls .control-group input.inline{margin:0 2px 2px 0}.wc-controls .control-group .changer+.changer{margin-top:2px}.wc-controls .subsetter-ui{position:relative;display:inline-block;max-width:100%;padding:3px;border:1px dashed #888;margin:5px 5px 0 0}.wc-controls .subsetter-ui .remove-btn{cursor:pointer;position:absolute;top:2px;right:2px}.wc-table{display:block}.wc-table .hidden{display:none!important}.wc-table .invisible{visibility:hidden!important}.wc-table>*{display:block}.wc-table .interactivity{display:inline-block;vertical-align:middle;margin:10px 0;padding:0}.wc-table .interactivity .wc-button{display:inline-block;border:2px solid gray;border-radius:4px;padding:2px 8px;margin:0 2px;cursor:pointer;background:#fff;color:#000}.wc-table .interactivity .wc-button:hover{background:#000;color:#fff}.wc-table .searchable-container{float:right;overflow:hidden}.wc-table .searchable-container input{margin:0 10px 0 0;padding:4px}.wc-table .sortable-container{margin-right:10px}.wc-table .sortable-container .instruction{margin-top:4px}.wc-table .sortable-container .sort-box{cursor:default;padding:2px 4px}.wc-table .sortable-container .sort-direction{font-weight:700;margin:3px}.wc-table .sortable-container .sort-box .remove-sort{font-weight:700;float:right;border:1px solid gray;margin-top:3px;padding:2px 3px;font-size:8px;background:#fff;color:red}.wc-table .sortable-container .sort-box .remove-sort:hover{cursor:pointer;background:red;color:#fff}.wc-table table{font-size:.9em;border-collapse:collapse}.wc-table table thead tr th{cursor:pointer;padding:2px 5px;border-bottom:2px solid #000;text-align:left}.wc-table table tbody tr:nth-child(even){background:#eee}.wc-table table tbody tr:hover{background:#ccc}.wc-table table tbody tr td{padding:2px 5px}.wc-table table tbody tr:last-child{border-bottom:1px solid #000}.wc-table table tbody tr.no-data td{color:red;font-weight:700}.wc-table .pagination-container{float:right}.wc-table .pagination-container a{text-decoration:none}.wc-table .pagination-container a:not(.active){border:none}.wc-table .exportable-container{float:left}.wc-table .exportable-container a{text-decoration:none}.loader{position:relative;width:20px;height:25px}.blockG{position:absolute;background-color:#eee;width:3px;height:8px;-moz-border-radius:4px 4px 0 0;-moz-transform:scale(.4);-moz-animation-name:fadeG;-moz-animation-duration:.48s;-moz-animation-iteration-count:infinite;-moz-animation-direction:linear;-webkit-border-radius:4px 4px 0 0;-webkit-transform:scale(.4);-webkit-animation-name:fadeG;-webkit-animation-duration:.48s;-webkit-animation-iteration-count:infinite;-webkit-animation-direction:linear;-ms-border-radius:4px 4px 0 0;-ms-transform:scale(.4);-ms-animation-name:fadeG;-ms-animation-duration:.48s;-ms-animation-iteration-count:infinite;-ms-animation-direction:linear;-o-border-radius:4px 4px 0 0;-o-transform:scale(.4);-o-animation-name:fadeG;-o-animation-duration:.48s;-o-animation-iteration-count:infinite;-o-animation-direction:linear;border-radius:4px 4px 0 0;transform:scale(.4);animation-name:fadeG;animation-duration:.48s;animation-iteration-count:infinite;animation-direction:linear}.rotate1{left:0;top:9px;-moz-animation-delay:.18s;-moz-transform:rotate(-90deg);-webkit-animation-delay:.18s;-webkit-transform:rotate(-90deg);-ms-animation-delay:.18s;-ms-transform:rotate(-90deg);-o-animation-delay:.18s;-o-transform:rotate(-90deg);animation-delay:.18s;transform:rotate(-90deg)}.rotate2{left:3px;top:3px;-moz-animation-delay:.24s;-moz-transform:rotate(-45deg);-webkit-animation-delay:.24s;-webkit-transform:rotate(-45deg);-ms-animation-delay:.24s;-ms-transform:rotate(-45deg);-o-animation-delay:.24s;-o-transform:rotate(-45deg);animation-delay:.24s;transform:rotate(-45deg)}.rotate3{left:8px;top:1px;-moz-animation-delay:.3s;-moz-transform:rotate(0);-webkit-animation-delay:.3s;-webkit-transform:rotate(0);-ms-animation-delay:.3s;-ms-transform:rotate(0);-o-animation-delay:.3s;-o-transform:rotate(0);animation-delay:.3s;transform:rotate(0)}.rotate4{right:3px;top:3px;-moz-animation-delay:.36s;-moz-transform:rotate(45deg);-webkit-animation-delay:.36s;-webkit-transform:rotate(45deg);-ms-animation-delay:.36s;-ms-transform:rotate(45deg);-o-animation-delay:.36s;-o-transform:rotate(45deg);animation-delay:.36s;transform:rotate(45deg)}.rotate5{right:0;top:9px;-moz-animation-delay:.42000000000000004s;-moz-transform:rotate(90deg);-webkit-animation-delay:.42000000000000004s;-webkit-transform:rotate(90deg);-ms-animation-delay:.42000000000000004s;-ms-transform:rotate(90deg);-o-animation-delay:.42000000000000004s;-o-transform:rotate(90deg);animation-delay:.42000000000000004s;transform:rotate(90deg)}.rotate6{right:3px;bottom:2px;-moz-animation-delay:.48s;-moz-transform:rotate(135deg);-webkit-animation-delay:.48s;-webkit-transform:rotate(135deg);-ms-animation-delay:.48s;-ms-transform:rotate(135deg);-o-animation-delay:.48s;-o-transform:rotate(135deg);animation-delay:.48s;transform:rotate(135deg)}.rotate7{bottom:0;left:8px;-moz-animation-delay:.5399999999999999s;-moz-transform:rotate(180deg);-webkit-animation-delay:.5399999999999999s;-webkit-transform:rotate(180deg);-ms-animation-delay:.5399999999999999s;-ms-transform:rotate(180deg);-o-animation-delay:.5399999999999999s;-o-transform:rotate(180deg);animation-delay:.5399999999999999s;transform:rotate(180deg)}.rotate8{left:3px;bottom:2px;-moz-animation-delay:.6s;-moz-transform:rotate(-135deg);-webkit-animation-delay:.6s;-webkit-transform:rotate(-135deg);-ms-animation-delay:.6s;-ms-transform:rotate(-135deg);-o-animation-delay:.6s;-o-transform:rotate(-135deg);animation-delay:.6s;transform:rotate(-135deg)}@-moz-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-webkit-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-ms-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@-o-keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}@keyframes fadeG{0%{background-color:#000}100%{background-color:#eee}}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 2c9b19f..e698a1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "webcharts",
- "version": "1.11.0",
+ "version": "1.9.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -14,174 +14,6 @@
"printj": "1.1.0"
}
},
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "babel-code-frame": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
- "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
- "dev": true,
- "requires": {
- "chalk": "1.1.3",
- "esutils": "2.0.2",
- "js-tokens": "3.0.2"
- }
- },
- "babel-helper-builder-binary-assignment-operator-visitor": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
- "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
- "dev": true,
- "requires": {
- "babel-helper-explode-assignable-expression": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-call-delegate": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
- "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
- "dev": true,
- "requires": {
- "babel-helper-hoist-variables": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-define-map": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
- "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
- "dev": true,
- "requires": {
- "babel-helper-function-name": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0",
- "lodash": "4.17.10"
- }
- },
- "babel-helper-explode-assignable-expression": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
- "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-function-name": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
- "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
- "dev": true,
- "requires": {
- "babel-helper-get-function-arity": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-get-function-arity": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
- "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-hoist-variables": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
- "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-optimise-call-expression": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
- "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-regex": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
- "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0",
- "lodash": "4.17.10"
- }
- },
- "babel-helper-remap-async-to-generator": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
- "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
- "dev": true,
- "requires": {
- "babel-helper-function-name": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-helper-replace-supers": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
- "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
- "dev": true,
- "requires": {
- "babel-helper-optimise-call-expression": "6.24.1",
- "babel-messages": "6.23.0",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-messages": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
- "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-check-es2015-constants": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
- "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
"babel-plugin-external-helpers": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz",
@@ -215,308 +47,13 @@
}
}
},
- "babel-plugin-syntax-async-functions": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
- "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
- "dev": true
- },
- "babel-plugin-syntax-exponentiation-operator": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
- "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
- "dev": true
- },
- "babel-plugin-syntax-trailing-function-commas": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
- "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
- "dev": true
- },
- "babel-plugin-transform-async-to-generator": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
- "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
- "dev": true,
- "requires": {
- "babel-helper-remap-async-to-generator": "6.24.1",
- "babel-plugin-syntax-async-functions": "6.13.0",
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-arrow-functions": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
- "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-block-scoped-functions": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
- "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-block-scoping": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
- "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0",
- "lodash": "4.17.10"
- }
- },
- "babel-plugin-transform-es2015-classes": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
- "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
- "dev": true,
- "requires": {
- "babel-helper-define-map": "6.26.0",
- "babel-helper-function-name": "6.24.1",
- "babel-helper-optimise-call-expression": "6.24.1",
- "babel-helper-replace-supers": "6.24.1",
- "babel-messages": "6.23.0",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-computed-properties": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
- "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-destructuring": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
- "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-duplicate-keys": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
- "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-for-of": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
- "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-function-name": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
- "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
- "dev": true,
- "requires": {
- "babel-helper-function-name": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-literals": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
- "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-modules-amd": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
- "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
- "dev": true,
- "requires": {
- "babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-modules-commonjs": {
- "version": "6.26.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
- "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
- "dev": true,
- "requires": {
- "babel-plugin-transform-strict-mode": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-modules-systemjs": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
- "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
- "dev": true,
- "requires": {
- "babel-helper-hoist-variables": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-modules-umd": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
- "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
- "dev": true,
- "requires": {
- "babel-plugin-transform-es2015-modules-amd": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-object-super": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
- "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
- "dev": true,
- "requires": {
- "babel-helper-replace-supers": "6.24.1",
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-parameters": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
- "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
- "dev": true,
- "requires": {
- "babel-helper-call-delegate": "6.24.1",
- "babel-helper-get-function-arity": "6.24.1",
- "babel-runtime": "6.26.0",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-shorthand-properties": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
- "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-spread": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
- "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-sticky-regex": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
- "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
- "dev": true,
- "requires": {
- "babel-helper-regex": "6.26.0",
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-template-literals": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
- "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-typeof-symbol": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
- "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-es2015-unicode-regex": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
- "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
- "dev": true,
- "requires": {
- "babel-helper-regex": "6.26.0",
- "babel-runtime": "6.26.0",
- "regexpu-core": "2.0.0"
- }
- },
- "babel-plugin-transform-exponentiation-operator": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
- "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
- "dev": true,
- "requires": {
- "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1",
- "babel-plugin-syntax-exponentiation-operator": "6.13.0",
- "babel-runtime": "6.26.0"
- }
- },
- "babel-plugin-transform-regenerator": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
- "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
- "dev": true,
- "requires": {
- "regenerator-transform": "0.10.1"
- }
- },
- "babel-plugin-transform-strict-mode": {
+ "babel-preset-es2015": {
"version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
- "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0"
- }
- },
- "babel-preset-env": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
- "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
"dev": true,
"requires": {
"babel-plugin-check-es2015-constants": "6.22.0",
- "babel-plugin-syntax-trailing-function-commas": "6.22.0",
- "babel-plugin-transform-async-to-generator": "6.24.1",
"babel-plugin-transform-es2015-arrow-functions": "6.22.0",
"babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
"babel-plugin-transform-es2015-block-scoping": "6.26.0",
@@ -528,7 +65,7 @@
"babel-plugin-transform-es2015-function-name": "6.24.1",
"babel-plugin-transform-es2015-literals": "6.22.0",
"babel-plugin-transform-es2015-modules-amd": "6.24.1",
- "babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
"babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
"babel-plugin-transform-es2015-modules-umd": "6.24.1",
"babel-plugin-transform-es2015-object-super": "6.24.1",
@@ -539,11 +76,626 @@
"babel-plugin-transform-es2015-template-literals": "6.22.0",
"babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
"babel-plugin-transform-es2015-unicode-regex": "6.24.1",
- "babel-plugin-transform-exponentiation-operator": "6.24.1",
- "babel-plugin-transform-regenerator": "6.26.0",
- "browserslist": "3.2.8",
- "invariant": "2.2.4",
- "semver": "5.5.0"
+ "babel-plugin-transform-regenerator": "6.26.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ }
+ },
+ "babel-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-define-map": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ }
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "dev": true,
+ "requires": {
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-regex": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ }
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "dev": true,
+ "requires": {
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ }
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "dev": true,
+ "requires": {
+ "babel-helper-define-map": "6.26.0",
+ "babel-helper-function-name": "6.24.1",
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
+ "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-strict-mode": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "dev": true,
+ "requires": {
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "dev": true,
+ "requires": {
+ "babel-helper-call-delegate": "6.24.1",
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "regexpu-core": "2.0.0"
+ }
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "0.10.1"
+ }
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "dev": true,
+ "requires": {
+ "core-js": "2.5.3",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "babel-template": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "lodash": "4.17.5"
+ }
+ },
+ "babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "debug": "2.6.9",
+ "globals": "9.18.0",
+ "invariant": "2.2.2",
+ "lodash": "4.17.5"
+ }
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "esutils": "2.0.2",
+ "lodash": "4.17.5",
+ "to-fast-properties": "1.0.3"
+ }
+ },
+ "babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "core-js": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
+ "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "invariant": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
+ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
+ "dev": true,
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+ "dev": true,
+ "requires": {
+ "js-tokens": "3.0.2"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
+ "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "private": "0.1.8"
+ }
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "dev": true,
+ "requires": {
+ "regenerate": "1.3.3",
+ "regjsgen": "0.2.0",
+ "regjsparser": "0.1.5"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "0.5.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ }
}
},
"babel-register": {
@@ -982,80 +1134,6 @@
}
}
},
- "babel-runtime": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
- "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
- "dev": true,
- "requires": {
- "core-js": "2.5.6",
- "regenerator-runtime": "0.11.1"
- }
- },
- "babel-template": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
- "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0",
- "babylon": "6.18.0",
- "lodash": "4.17.10"
- }
- },
- "babel-traverse": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
- "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
- "dev": true,
- "requires": {
- "babel-code-frame": "6.26.0",
- "babel-messages": "6.23.0",
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0",
- "babylon": "6.18.0",
- "debug": "2.6.9",
- "globals": "9.18.0",
- "invariant": "2.2.4",
- "lodash": "4.17.10"
- }
- },
- "babel-types": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
- "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "esutils": "2.0.2",
- "lodash": "4.17.10",
- "to-fast-properties": "1.0.3"
- }
- },
- "babylon": {
- "version": "6.18.0",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
- "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
- "dev": true
- },
- "browserslist": {
- "version": "3.2.8",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
- "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
- "dev": true,
- "requires": {
- "caniuse-lite": "1.0.30000846",
- "electron-to-chromium": "1.3.48"
- }
- },
- "caniuse-lite": {
- "version": "1.0.30000846",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000846.tgz",
- "integrity": "sha512-qxUOHr5mTaadWH1ap0ueivHd8x42Bnemcn+JutVr7GWmm2bU4zoBhjuv5QdXgALQnnT626lOQros7cCDf8PwCg==",
- "dev": true
- },
"cfb": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.1.tgz",
@@ -1074,19 +1152,6 @@
}
}
},
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "dev": true,
- "requires": {
- "ansi-styles": "2.2.1",
- "escape-string-regexp": "1.0.5",
- "has-ansi": "2.0.0",
- "strip-ansi": "3.0.1",
- "supports-color": "2.0.0"
- }
- },
"clean-css-cli": {
"version": "4.1.10",
"resolved": "https://registry.npmjs.org/clean-css-cli/-/clean-css-cli-4.1.10.tgz",
@@ -1245,12 +1310,6 @@
"typedarray": "0.0.6"
}
},
- "core-js": {
- "version": "2.5.6",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz",
- "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==",
- "dev": true
- },
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -1271,33 +1330,6 @@
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
"integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g="
},
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "electron-to-chromium": {
- "version": "1.3.48",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz",
- "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=",
- "dev": true
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
- "dev": true
- },
"exit-on-epipe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
@@ -1502,21 +1534,6 @@
"integrity": "sha1-V3Z3t/3L5vr3xGHxgB00E3zaQ1Q=",
"optional": true
},
- "globals": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
- "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
- "dev": true
- },
- "has-ansi": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
- "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
- "dev": true,
- "requires": {
- "ansi-regex": "2.1.1"
- }
- },
"he": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
@@ -1527,27 +1544,12 @@
"version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
- "invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
- "dev": true,
- "requires": {
- "loose-envify": "1.3.1"
- }
- },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"optional": true
},
- "js-tokens": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
- "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
- "dev": true
- },
"js-xlsx": {
"version": "0.8.22",
"resolved": "https://registry.npmjs.org/js-xlsx/-/js-xlsx-0.8.22.tgz",
@@ -2268,12 +2270,6 @@
}
}
},
- "jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
- "dev": true
- },
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
@@ -2289,21 +2285,6 @@
"pako": "0.2.9"
}
},
- "lodash": {
- "version": "4.17.10",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
- "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
- "dev": true
- },
- "loose-envify": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
- "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
- "dev": true,
- "requires": {
- "js-tokens": "3.0.2"
- }
- },
"mocha": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz",
@@ -2572,12 +2553,6 @@
}
}
},
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
"pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
@@ -2587,7 +2562,7 @@
"prettier": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.4.4.tgz",
- "integrity": "sha1-qNFEexTJv2fm1CDcrdEPuaT61lo=",
+ "integrity": "sha512-GuuPazIvjW1DG26yLQgO+nagmRF/h9M4RaCtZWqu/eFW7csdZkQEwPJUeXX10d+LzmCnR9DuIZndqIOn3p2YoA==",
"dev": true
},
"printj": {
@@ -2595,12 +2570,6 @@
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.0.tgz",
"integrity": "sha512-NbiNBOQ0GioHyeD3ni8wZB7ZmfU7mxIrqhWR5XSreX3rUVvk5UOwpzxOnWqrLdCtoBbdQ40sEwC+nXxxjlUo0A=="
},
- "private": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
- "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
- "dev": true
- },
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@@ -2630,55 +2599,6 @@
}
}
},
- "regenerate": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
- "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
- "dev": true
- },
- "regenerator-runtime": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
- "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
- "dev": true
- },
- "regenerator-transform": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
- "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "babel-types": "6.26.0",
- "private": "0.1.8"
- }
- },
- "regexpu-core": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
- "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
- "dev": true,
- "requires": {
- "regenerate": "1.4.0",
- "regjsgen": "0.2.0",
- "regjsparser": "0.1.5"
- }
- },
- "regjsgen": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
- "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
- "dev": true
- },
- "regjsparser": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
- "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
- "dev": true,
- "requires": {
- "jsesc": "0.5.0"
- }
- },
"rollup": {
"version": "0.53.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.53.3.tgz",
@@ -3192,12 +3112,6 @@
"integrity": "sha1-/kyEYDl/nqqqWOc75GJzQIpF4iM=",
"optional": true
},
- "semver": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
- "dev": true
- },
"ssf": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.8.2.tgz",
@@ -3218,27 +3132,6 @@
"safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz"
}
},
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "2.1.1"
- }
- },
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
- "dev": true
- },
- "to-fast-properties": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
- "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
- "dev": true
- },
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
diff --git a/package.json b/package.json
index fc819d9..30dedc7 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "webcharts",
"description": "A library for creating flexible, interactive charts",
- "version": "1.11.0",
+ "version": "1.10.0",
"keywords": [
"charts",
"javascript",
@@ -33,7 +33,6 @@
"test-controls": "mocha --timeout 5000 --require babel-register --recursive ./test/controls/*.js",
"test-miscellaneous": "mocha --timeout 5000 --require babel-register --recursive ./test/miscellaneous/*.js",
"test-multiply": "mocha --timeout 5000 --require babel-register --recursive ./test/multiply/*.js",
- "test-new": "mocha --timeout 5000 --require babel-register --recursive ./test/testNewUnitTests.js",
"test-table": "mocha --timeout 5000 --require babel-register --recursive ./test/table/*.js",
"watch": "rollup -c -w"
},
@@ -48,7 +47,7 @@
},
"devDependencies": {
"babel-plugin-external-helpers": "^6.22.0",
- "babel-preset-env": "^1.7.0",
+ "babel-preset-es2015": "^6.0.0",
"babel-register": "6",
"clean-css-cli": "^4.0.0",
"expect": "1",
diff --git a/rollup.config.js b/rollup.config.js
index 994272c..d95bb6d 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,27 +1,21 @@
import babel from 'rollup-plugin-babel';
-var pkg = require('./package.json');
-
-module.exports = {
- input: pkg.module,
+export default {
+ input: './src/index.js',
output: {
name: 'webCharts',
- file: pkg.main,
+ file: './build/webcharts.js',
format: 'umd',
globals: {
d3: 'd3'
- },
+ }
},
- external: (function() {
- var dependencies = pkg.dependencies;
-
- return Object.keys(dependencies);
- }()),
+ external: ['d3'],
plugins: [
babel({
exclude: 'node_modules/**',
presets: [
- [ 'env', {modules: false} ]
+ [ 'es2015' , {modules: false} ]
],
plugins: [
'external-helpers'
@@ -29,4 +23,4 @@ module.exports = {
babelrc: false
})
]
-};
+}
diff --git a/src/chart/init/checkRequired.js b/src/chart/checkRequired.js
similarity index 100%
rename from src/chart/init/checkRequired.js
rename to src/chart/checkRequired.js
diff --git a/src/chart/consolidateData.js b/src/chart/consolidateData.js
new file mode 100644
index 0000000..db58362
--- /dev/null
+++ b/src/chart/consolidateData.js
@@ -0,0 +1,110 @@
+import naturalSorter from '../dataOps/naturalSorter';
+import { set, merge, ascending, nest, min, extent } from 'd3';
+
+export default function consolidateData(raw) {
+ let config = this.config;
+ let all_data = [];
+ let all_x = [];
+ let all_y = [];
+
+ this.setDefaults();
+
+ //apply filters from associated controls objects
+ this.filtered_data = raw;
+ if (this.filters.length) {
+ this.filters.forEach(e => {
+ this.filtered_data = this.filtered_data.filter(d => {
+ return e.val === 'All'
+ ? d
+ : e.val instanceof Array ? e.val.indexOf(d[e.col]) > -1 : d[e.col] === e.val;
+ });
+ });
+ }
+
+ //create data for each set of marks
+ config.marks.forEach((e, i) => {
+ if (e.type !== 'bar') {
+ e.arrange = null;
+ e.split = null;
+ }
+ let mark_info = e.per ? this.transformData(raw, e) : { data: [], x_dom: [], y_dom: [] };
+
+ all_data.push(mark_info.data);
+ all_x.push(mark_info.x_dom);
+ all_y.push(mark_info.y_dom);
+ this.marks[i] = {
+ id: e.id,
+ type: e.type,
+ per: e.per,
+ data: mark_info.data,
+ split: e.split,
+ text: e.text,
+ arrange: e.arrange,
+ order: e.order,
+ summarizeX: e.summarizeX,
+ summarizeY: e.summarizeY,
+ tooltip: e.tooltip,
+ radius: e.radius,
+ attributes: e.attributes,
+ values: e.values
+ };
+ });
+
+ if (config.x.type === 'ordinal') {
+ if (config.x.domain) {
+ this.x_dom = config.x.domain;
+ } else if (config.x.order) {
+ this.x_dom = set(merge(all_x))
+ .values()
+ .sort((a, b) => ascending(config.x.order.indexOf(a), config.x.order.indexOf(b)));
+ } else if (config.x.sort && config.x.sort === 'alphabetical-ascending') {
+ this.x_dom = set(merge(all_x)).values().sort(naturalSorter);
+ } else if (config.y.type === 'time' && config.x.sort === 'earliest') {
+ this.x_dom = nest()
+ .key(d => d[config.x.column])
+ .rollup(d => {
+ return d.map(m => m[config.y.column]).filter(f => f instanceof Date);
+ })
+ .entries(this.raw_data)
+ .sort((a, b) => min(b.values) - min(a.values))
+ .map(m => m.key);
+ } else if (!config.x.sort || config.x.sort === 'alphabetical-descending') {
+ this.x_dom = set(merge(all_x)).values().sort(naturalSorter);
+ } else {
+ this.x_dom = set(merge(all_x)).values();
+ }
+ } else if (config.marks.map(m => m.summarizeX === 'percent').indexOf(true) > -1) {
+ this.x_dom = [0, 1];
+ } else {
+ this.x_dom = extent(merge(all_x));
+ }
+
+ if (config.y.type === 'ordinal') {
+ if (config.y.domain) {
+ this.y_dom = config.y.domain;
+ } else if (config.y.order) {
+ this.y_dom = set(merge(all_y))
+ .values()
+ .sort((a, b) => ascending(config.y.order.indexOf(a), config.y.order.indexOf(b)));
+ } else if (config.y.sort && config.y.sort === 'alphabetical-ascending') {
+ this.y_dom = set(merge(all_y)).values().sort(naturalSorter);
+ } else if (config.x.type === 'time' && config.y.sort === 'earliest') {
+ this.y_dom = nest()
+ .key(d => d[config.y.column])
+ .rollup(d => {
+ return d.map(m => m[config.x.column]).filter(f => f instanceof Date);
+ })
+ .entries(this.raw_data)
+ .sort((a, b) => min(b.values) - min(a.values))
+ .map(m => m.key);
+ } else if (!config.y.sort || config.y.sort === 'alphabetical-descending') {
+ this.y_dom = set(merge(all_y)).values().sort(naturalSorter).reverse();
+ } else {
+ this.y_dom = set(merge(all_y)).values();
+ }
+ } else if (config.marks.map(m => m.summarizeY === 'percent').indexOf(true) > -1) {
+ this.y_dom = [0, 1];
+ } else {
+ this.y_dom = extent(merge(all_y));
+ }
+}
diff --git a/src/chart/draw.js b/src/chart/draw.js
index f31e7d0..7d23c13 100644
--- a/src/chart/draw.js
+++ b/src/chart/draw.js
@@ -1,18 +1,19 @@
import { select } from 'd3';
export default function draw(raw_data, processed_data) {
- const chart = this;
- const config = this.config;
-
- //if pre-processing callback, run it now
- this.events.onPreprocess.call(this);
+ var context = this;
+ let config = this.config;
+ let aspect2 = 1 / config.aspect;
/////////////////////////
// Data prep pipeline //
/////////////////////////
+ //if pre-processing callback, run it now
+ this.events.onPreprocess.call(this);
+
// if user passed raw_data to chart.draw(), use that, otherwise use chart.raw_data
- const raw = raw_data ? raw_data : this.raw_data ? this.raw_data : [];
+ let raw = raw_data ? raw_data : this.raw_data ? this.raw_data : [];
// warn the user about the perils of "processed_data"
if (processed_data) {
@@ -22,7 +23,7 @@ export default function draw(raw_data, processed_data) {
}
//Call consolidateData - this applies filters from controls and prepares data for each set of marks.
- this.consolidateData(raw);
+ let data = processed_data || this.consolidateData(raw);
/////////////////////////////
// Prepare scales and axes //
@@ -33,14 +34,14 @@ export default function draw(raw_data, processed_data) {
this.setColorScale();
let max_width = config.max_width ? config.max_width : div_width;
- this.raw_width = config.x.type === 'ordinal' && +config.x.range_band
- ? (+config.x.range_band + config.x.range_band * config.padding) * this.x_dom.length
+ this.raw_width = config.x.type === 'ordinal' && +config.range_band
+ ? (+config.range_band + config.range_band * config.padding) * this.x_dom.length
: config.resizable ? max_width : config.width ? config.width : div_width;
- this.raw_height = config.y.type === 'ordinal' && +config.y.range_band
- ? (+config.y.range_band + config.y.range_band * config.padding) * this.y_dom.length
+ this.raw_height = config.y.type === 'ordinal' && +config.range_band
+ ? (+config.range_band + config.range_band * config.padding) * this.y_dom.length
: config.resizable
- ? max_width * (1 / config.aspect)
- : config.height ? config.height : div_width * (1 / config.aspect);
+ ? max_width * aspect2
+ : config.height ? config.height : div_width * aspect2;
let pseudo_width = this.svg.select('.overlay').attr('width')
? this.svg.select('.overlay').attr('width')
@@ -64,11 +65,11 @@ export default function draw(raw_data, processed_data) {
this.yScaleAxis(pseudo_height);
if (config.resizable && typeof window !== 'undefined') {
- select(window).on('resize.' + this.element + this.id, function() {
- chart.resize();
+ select(window).on('resize.' + context.element + context.id, function() {
+ context.resize();
});
} else if (typeof window !== 'undefined') {
- select(window).on('resize.' + this.element + this.id, null);
+ select(window).on('resize.' + context.element + context.id, null);
}
this.events.onDraw.call(this);
diff --git a/src/chart/draw/consolidateData.js b/src/chart/draw/consolidateData.js
deleted file mode 100644
index 8d48e2d..0000000
--- a/src/chart/draw/consolidateData.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import naturalSorter from '../../dataOps/naturalSorter';
-import { set, merge, ascending, nest, min, extent } from 'd3';
-import setDomain from './consolidateData/setDomain';
-
-export default function consolidateData(raw) {
- this.setDefaults();
-
- //Apply filters from associated controls objects to raw data.
- this.filtered_data = raw;
- if (this.filters.length) {
- this.filters.forEach(filter => {
- this.filtered_data = this.filtered_data.filter(d => {
- return filter.val === 'All'
- ? d
- : filter.val instanceof Array
- ? filter.val.indexOf(d[filter.col]) > -1
- : d[filter.col] === filter.val;
- });
- });
- }
-
- //Summarize data for each mark.
- this.config.marks.forEach((mark, i) => {
- if (mark.type !== 'bar') {
- mark.arrange = null;
- mark.split = null;
- }
-
- const mark_info = mark.per
- ? this.transformData(raw, mark)
- : {
- data: [],
- x_dom: [],
- y_dom: []
- };
-
- this.marks[i] = {
- id: mark.id,
- type: mark.type,
- per: mark.per,
- data: mark_info.data,
- x_dom: mark_info.x_dom,
- y_dom: mark_info.y_dom,
- split: mark.split,
- text: mark.text,
- arrange: mark.arrange,
- order: mark.order,
- summarizeX: mark.summarizeX,
- summarizeY: mark.summarizeY,
- tooltip: mark.tooltip,
- radius: mark.radius,
- attributes: mark.attributes,
- values: mark.values
- };
- });
-
- //Set domains given extents of summarized mark data.
- setDomain.call(this, 'x');
- setDomain.call(this, 'y');
-}
diff --git a/src/chart/draw/consolidateData/setDomain.js b/src/chart/draw/consolidateData/setDomain.js
deleted file mode 100644
index c9ba5b8..0000000
--- a/src/chart/draw/consolidateData/setDomain.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import naturalSorter from '../../../dataOps/naturalSorter';
-import { set, merge, ascending, nest, extent } from 'd3';
-
-export default function setDomain(axis) {
- const otherAxis = axis === 'x' ? 'y' : 'x';
-
- if (this.config[axis].type === 'ordinal') {
- //ordinal domains
- if (this.config[axis].domain) {
- //user-defined domain
- this[axis + '_dom'] = this.config[axis].domain;
- } else if (this.config[axis].order) {
- //data-driven domain with user-defined domain order
- this[axis + '_dom'] = set(merge(this.marks.map(mark => mark[axis + '_dom'])))
- .values()
- .sort((a, b) =>
- ascending(
- this.config[axis].order.indexOf(a),
- this.config[axis].order.indexOf(b)
- )
- );
- } else if (this.config[axis].sort && this.config[axis].sort === 'alphabetical-ascending') {
- //data-driven domain with user-defined domain sort algorithm that sorts the axis
- //alphanumerically, first to last
- this[axis + '_dom'] = set(merge(this.marks.map(mark => mark[axis + '_dom'])))
- .values()
- .sort(naturalSorter);
- } else if (
- ['time', 'linear'].indexOf(this.config[otherAxis].type) > -1 &&
- this.config[axis].sort === 'earliest'
- ) {
- //data-driven domain plotted against a time or linear axis that sorts the axis values
- //by earliest event/datum; generally used with timeline charts
- this[axis + '_dom'] = nest()
- .key(d => d[this.config[axis].column])
- .rollup(d => {
- return d
- .map(m => m[this.config[otherAxis].column])
- .filter(f => f instanceof Date);
- })
- .entries(this.raw_data)
- .sort((a, b) => min(b.values) - min(a.values))
- .map(m => m.key);
- } else if (
- !this.config[axis].sort ||
- this.config[axis].sort === 'alphabetical-descending'
- ) {
- //data-driven domain with default/user-defined domain sort algorithm that sorts the
- //axis alphanumerically, last to first
- this[axis + '_dom'] = set(merge(this.marks.map(mark => mark[axis + '_dom'])))
- .values()
- .sort(naturalSorter)
- .reverse();
- } else {
- //data-driven domain with an invalid user-defined sort algorithm that captures a unique
- //set of values as they appear in the data
- this[axis + '_dom'] = set(merge(this.marks.map(mark => mark[axis + '_dom']))).values();
- }
- } else if (
- this.config.marks
- .map(m => m['summarize' + otherAxis.toUpperCase()] === 'percent')
- .indexOf(true) > -1
- ) {
- //rate domains run from 0 to 1
- this[axis + '_dom'] = [0, 1];
- } else {
- //continuous domains run from the minimum to the maximum raw value
- //TODO: they should really run from the minimum to the maximum summarized value, e.g. a
- //TODO: means over time chart should plot over the range of the means, not the range of the
- //TODO: raw data
- this[axis + '_dom'] = extent(merge(this.marks.map(mark => mark[axis + '_dom'])));
- }
-
- //Give the domain a range when the range of the variable is 0.
- if (this.config[axis].type === 'linear' && this[axis + '_dom'][0] === this[axis + '_dom'][1])
- this[axis + '_dom'] = this[axis + '_dom'][0] !== 0
- ? [
- this[axis + '_dom'][0] - this[axis + '_dom'][0] * 0.01,
- this[axis + '_dom'][1] + this[axis + '_dom'][1] * 0.01
- ]
- : [-1, 1];
-
- return this[axis + '_dom'];
-}
diff --git a/src/chart/draw/consolidateData/transformData.js b/src/chart/draw/consolidateData/transformData.js
deleted file mode 100644
index 356e36b..0000000
--- a/src/chart/draw/consolidateData/transformData.js
+++ /dev/null
@@ -1,188 +0,0 @@
-import cleanData from './transformData/cleanData';
-import makeNest from './transformData/makeNest';
-import { set, extent, merge } from 'd3';
-
-//////////////////////////////////////////////////////////
-// transformData(raw, mark) provides specifications and data for
-// each set of marks. As such, it is called once for each
-// item specified in the config.marks array.
-//
-// parameters
-// raw - the raw data for use in the mark. Filters from controls
-// are typically already applied.
-// mark - a single mark object from config.marks
-////////////////////////////////////////////////////////
-
-export default function transformData(raw, mark) {
- //convenience mappings
- const config = this.config;
- const x_behavior = config.x.behavior || 'raw';
- const y_behavior = config.y.behavior || 'raw';
- const sublevel = mark.type === 'line'
- ? config.x.column
- : mark.type === 'bar' && mark.split ? mark.split : null;
-
- //////////////////////////////////////////////////////////////////////////////////
- // DATA PREP
- // prepare data based on the properties of the mark - drop missing records, etc
- //////////////////////////////////////////////////////////////////////////////////
- const cleaned = cleanData.call(this, mark, raw);
-
- //prepare nested data required for bar charts
- let raw_nest;
- if (mark.type === 'bar') {
- raw_nest = mark.arrange !== 'stacked'
- ? makeNest.call(this, mark, cleaned, sublevel)
- : makeNest.call(this, mark, cleaned);
- } else if (mark.summarizeX === 'count' || mark.summarizeY === 'count') {
- raw_nest = makeNest.call(this, mark, cleaned);
- }
-
- // Get the domain for the mark based on the raw data
- let raw_dom_x = mark.summarizeX === 'cumulative'
- ? [0, cleaned.length]
- : config.x.type === 'ordinal'
- ? set(cleaned.map(m => m[config.x.column])).values().filter(f => f)
- : mark.split && mark.arrange !== 'stacked'
- ? extent(merge(raw_nest.nested.map(m => m.values.map(p => p.values.raw.length))))
- : mark.summarizeX === 'count'
- ? extent(raw_nest.nested.map(m => m.values.raw.length))
- : extent(cleaned.map(m => +m[config.x.column]).filter(f => +f || +f === 0));
-
- let raw_dom_y = mark.summarizeY === 'cumulative'
- ? [0, cleaned.length]
- : config.y.type === 'ordinal'
- ? set(cleaned.map(m => m[config.y.column])).values().filter(f => f)
- : mark.split && mark.arrange !== 'stacked'
- ? extent(merge(raw_nest.nested.map(m => m.values.map(p => p.values.raw.length))))
- : mark.summarizeY === 'count'
- ? extent(raw_nest.nested.map(m => m.values.raw.length))
- : extent(cleaned.map(m => +m[config.y.column]).filter(f => +f || +f === 0));
-
- let filtered = cleaned;
-
- let filt1_xs = [];
- let filt1_ys = [];
- if (this.filters.length) {
- this.filters.forEach(e => {
- filtered = filtered.filter(d => {
- return e.val === 'All'
- ? d
- : e.val instanceof Array ? e.val.indexOf(d[e.col]) > -1 : d[e.col] === e.val;
- });
- });
- //get domain for all non-All values of first filter
- if (config.x.behavior === 'firstfilter' || config.y.behavior === 'firstfilter') {
- this.filters[0].choices.filter(f => f !== 'All').forEach(e => {
- let perfilter = cleaned.filter(f => f[this.filters[0].col] === e);
- let filt_nested = makeNest.call(this, mark, perfilter, sublevel);
- filt1_xs.push(filt_nested.dom_x);
- filt1_ys.push(filt_nested.dom_y);
- });
- }
- }
-
- //filter on mark-specific instructions
- if (mark.values) {
- for (let a in mark.values) {
- filtered = filtered.filter(f => {
- return mark.values[a].indexOf(f[a]) > -1;
- });
- }
- }
- let filt1_dom_x = extent(merge(filt1_xs));
- let filt1_dom_y = extent(merge(filt1_ys));
-
- let current_nested = makeNest.call(this, mark, filtered, sublevel);
-
- let flex_dom_x = current_nested.dom_x;
- let flex_dom_y = current_nested.dom_y;
-
- if (mark.type === 'bar') {
- if (config.y.type === 'ordinal' && mark.summarizeX === 'count') {
- config.x.domain = config.x.domain ? [0, config.x.domain[1]] : [0, null];
- } else if (config.x.type === 'ordinal' && mark.summarizeY === 'count') {
- config.y.domain = config.y.domain ? [0, config.y.domain[1]] : [0, null];
- }
- }
-
- //several criteria must be met in order to use the 'firstfilter' domain
- let nonall = Boolean(
- this.filters.length &&
- this.filters[0].val !== 'All' &&
- this.filters.slice(1).filter(f => f.val === 'All').length === this.filters.length - 1
- );
-
- let pre_x_dom = !this.filters.length
- ? flex_dom_x
- : x_behavior === 'raw'
- ? raw_dom_x
- : nonall && x_behavior === 'firstfilter' ? filt1_dom_x : flex_dom_x;
- let pre_y_dom = !this.filters.length
- ? flex_dom_y
- : y_behavior === 'raw'
- ? raw_dom_y
- : nonall && y_behavior === 'firstfilter' ? filt1_dom_y : flex_dom_y;
-
- let x_dom = config.x_dom
- ? config.x_dom
- : config.x.type === 'ordinal' && config.x.behavior === 'flex'
- ? set(filtered.map(m => m[config.x.column])).values()
- : config.x.type === 'ordinal'
- ? set(cleaned.map(m => m[config.x.column])).values()
- : pre_x_dom;
-
- let y_dom = config.y_dom
- ? config.y_dom
- : config.y.type === 'ordinal' && config.y.behavior === 'flex'
- ? set(filtered.map(m => m[config.y.column])).values()
- : config.y.type === 'ordinal'
- ? set(cleaned.map(m => m[config.y.column])).values()
- : pre_y_dom;
-
- //set lower limit of linear domain to 0 when other axis is ordinal and mark type is set to 'bar', provided no values are negative
- if (mark.type === 'bar') {
- if (
- config.x.behavior !== 'flex' &&
- config.x.type === 'linear' &&
- config.y.type === 'ordinal' &&
- raw_dom_x[0] >= 0
- )
- x_dom[0] = 0;
-
- if (
- config.y.behavior !== 'flex' &&
- config.x.type === 'ordinal' &&
- config.y.type === 'linear' &&
- raw_dom_y[0] >= 0
- )
- y_dom[0] = 0;
- }
-
- //update domains with those specified in the config
- if (config.x.domain && (config.x.domain[0] || config.x.domain[0] === 0)) {
- x_dom[0] = config.x.domain[0];
- }
- if (config.x.domain && (config.x.domain[1] || config.x.domain[1] === 0)) {
- x_dom[1] = config.x.domain[1];
- }
- if (config.y.domain && (config.y.domain[0] || config.y.domain[0] === 0)) {
- y_dom[0] = config.y.domain[0];
- }
- if (config.y.domain && (config.y.domain[1] || config.y.domain[1] === 0)) {
- y_dom[1] = config.y.domain[1];
- }
-
- if (config.x.type === 'ordinal' && !config.x.order) {
- config.x.order = current_nested.totalOrder;
- }
- if (config.y.type === 'ordinal' && !config.y.order) {
- config.y.order = current_nested.totalOrder;
- }
-
- this.current_data = current_nested.nested;
-
- this.events.onDatatransform.call(this);
-
- return { config: mark, data: current_nested.nested, x_dom: x_dom, y_dom: y_dom };
-}
diff --git a/src/chart/draw/consolidateData/transformData/cleanData.js b/src/chart/draw/consolidateData/transformData/cleanData.js
deleted file mode 100644
index 808802c..0000000
--- a/src/chart/draw/consolidateData/transformData/cleanData.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { time } from 'd3';
-
-export default function cleanData(mark, raw) {
- const dateConvert = time.format(this.config.date_format);
- let clean = raw;
- // only use data for the current mark
- clean = mark.per && mark.per.length ? clean.filter(f => f[mark.per[0]] !== undefined) : clean;
-
- // Make sure data has x and y values
- if (this.config.x.column) {
- clean = clean.filter(f => [undefined, null].indexOf(f[this.config.x.column]) < 0);
- }
- if (this.config.y.column) {
- clean = clean.filter(f => [undefined, null].indexOf(f[this.config.y.column]) < 0);
- }
-
- //check that x and y have the correct formats
- if (this.config.x.type === 'time') {
- clean = clean.filter(
- f =>
- f[this.config.x.column] instanceof Date
- ? f[this.config.x.column]
- : dateConvert.parse(f[this.config.x.column])
- );
- clean.forEach(
- e =>
- (e[this.config.x.column] = e[this.config.x.column] instanceof Date
- ? e[this.config.x.column]
- : dateConvert.parse(e[this.config.x.column]))
- );
- }
- if (this.config.y.type === 'time') {
- clean = clean.filter(
- f =>
- f[this.config.y.column] instanceof Date
- ? f[this.config.y.column]
- : dateConvert.parse(f[this.config.y.column])
- );
- clean.forEach(
- e =>
- (e[this.config.y.column] = e[this.config.y.column] instanceof Date
- ? e[this.config.y.column]
- : dateConvert.parse(e[this.config.y.column]))
- );
- }
-
- if ((this.config.x.type === 'linear' || this.config.x.type === 'log') && this.config.x.column) {
- clean = clean.filter(f => {
- return mark.summarizeX !== 'count' && mark.summarizeX !== 'percent'
- ? !(isNaN(f[this.config.x.column]) || /^\s*$/.test(f[this.config.x.column])) // is or coerces to a number and is not a string that coerces to 0
- : f;
- });
- }
- if ((this.config.y.type === 'linear' || this.config.y.type === 'log') && this.config.y.column) {
- clean = clean.filter(f => {
- return mark.summarizeY !== 'count' && mark.summarizeY !== 'percent'
- ? !(isNaN(f[this.config.y.column]) || /^\s*$/.test(f[this.config.y.column])) // is or coerces to a number and is not a string that coerces to 0
- : f;
- });
- }
-
- return clean;
-}
diff --git a/src/chart/draw/consolidateData/transformData/makeNest.js b/src/chart/draw/consolidateData/transformData/makeNest.js
deleted file mode 100644
index eacdd38..0000000
--- a/src/chart/draw/consolidateData/transformData/makeNest.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import { nest, scale, extent, range, ascending, quantile, sum, merge, descending } from 'd3';
-import naturalSorter from '../../../../dataOps/naturalSorter';
-import summarize from '../../../../dataOps/summarize';
-
-export default function makeNest(mark, entries, sublevel) {
- let dom_xs = [];
- let dom_ys = [];
- let this_nest = nest();
- let totalOrder;
-
- if (
- (this.config.x.type === 'linear' && this.config.x.bin) ||
- (this.config.y.type === 'linear' && this.config.y.bin)
- ) {
- let xy = this.config.x.type === 'linear' && this.config.x.bin ? 'x' : 'y';
- let quant = scale
- .quantile()
- .domain(extent(entries.map(m => +m[this.config[xy].column])))
- .range(range(+this.config[xy].bin));
-
- entries.forEach(e => (e.wc_bin = quant(e[this.config[xy].column])));
-
- this_nest.key(d => quant.invertExtent(d.wc_bin));
- } else {
- this_nest.key(d => mark.per.map(m => d[m]).join(' '));
- }
-
- if (sublevel) {
- this_nest.key(d => d[sublevel]);
- this_nest.sortKeys((a, b) => {
- return this.config.x.type === 'time'
- ? ascending(new Date(a), new Date(b))
- : this.config.x.order
- ? ascending(this.config.x.order.indexOf(a), this.config.x.order.indexOf(b))
- : sublevel === this.config.color_by && this.config.legend.order
- ? ascending(
- this.config.legend.order.indexOf(a),
- this.config.legend.order.indexOf(b)
- )
- : this.config.x.type === 'ordinal' || this.config.y.type === 'ordinal'
- ? naturalSorter(a, b)
- : ascending(+a, +b);
- });
- }
- this_nest.rollup(r => {
- let obj = { raw: r };
- let y_vals = r.map(m => m[this.config.y.column]).sort(ascending);
- let x_vals = r.map(m => m[this.config.x.column]).sort(ascending);
- obj.x = this.config.x.type === 'ordinal'
- ? r[0][this.config.x.column]
- : summarize(x_vals, mark.summarizeX);
- obj.y = this.config.y.type === 'ordinal'
- ? r[0][this.config.y.column]
- : summarize(y_vals, mark.summarizeY);
-
- obj.x_q25 = this.config.error_bars && this.config.y.type === 'ordinal'
- ? quantile(x_vals, 0.25)
- : obj.x;
- obj.x_q75 = this.config.error_bars && this.config.y.type === 'ordinal'
- ? quantile(x_vals, 0.75)
- : obj.x;
- obj.y_q25 = this.config.error_bars ? quantile(y_vals, 0.25) : obj.y;
- obj.y_q75 = this.config.error_bars ? quantile(y_vals, 0.75) : obj.y;
- dom_xs.push([obj.x_q25, obj.x_q75, obj.x]);
- dom_ys.push([obj.y_q25, obj.y_q75, obj.y]);
-
- if (mark.summarizeY === 'cumulative') {
- let interm = entries.filter(f => {
- return this.config.x.type === 'time'
- ? new Date(f[this.config.x.column]) <= new Date(r[0][this.config.x.column])
- : +f[this.config.x.column] <= +r[0][this.config.x.column];
- });
- if (mark.per.length) {
- interm = interm.filter(f => f[mark.per[0]] === r[0][mark.per[0]]);
- }
-
- let cumul = this.config.x.type === 'time'
- ? interm.length
- : sum(
- interm.map(
- m =>
- +m[this.config.y.column] || +m[this.config.y.column] === 0
- ? +m[this.config.y.column]
- : 1
- )
- );
- dom_ys.push([cumul]);
- obj.y = cumul;
- }
- if (mark.summarizeX === 'cumulative') {
- let interm = entries.filter(f => {
- return this.config.y.type === 'time'
- ? new Date(f[this.config.y.column]) <= new Date(r[0][this.config.y.column])
- : +f[this.config.y.column] <= +r[0][this.config.y.column];
- });
- if (mark.per.length) {
- interm = interm.filter(f => f[mark.per[0]] === r[0][mark.per[0]]);
- }
- dom_xs.push([interm.length]);
- obj.x = interm.length;
- }
-
- return obj;
- });
-
- let test = this_nest.entries(entries);
-
- let dom_x = extent(merge(dom_xs));
- let dom_y = extent(merge(dom_ys));
-
- if (sublevel && mark.type === 'bar' && mark.split) {
- //calculate percentages in bars
- test.forEach(e => {
- let axis = this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ? 'y'
- : 'x';
- e.total = sum(e.values.map(m => +m.values[axis]));
- let counter = 0;
- e.values.forEach((v, i) => {
- if (
- this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ) {
- v.values.y = mark.summarizeY === 'percent'
- ? v.values.y / e.total
- : v.values.y || 0;
- counter += +v.values.y;
- v.values.start = e.values[i - 1] ? counter : v.values.y;
- } else {
- v.values.x = mark.summarizeX === 'percent'
- ? v.values.x / e.total
- : v.values.x || 0;
- v.values.start = counter;
- counter += +v.values.x;
- }
- });
- });
-
- if (mark.arrange === 'stacked') {
- if (
- this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ) {
- dom_y = extent(test.map(m => m.total));
- }
- if (
- this.config.y.type === 'ordinal' ||
- (this.config.y.type === 'linear' && this.config.y.bin)
- ) {
- dom_x = extent(test.map(m => m.total));
- }
- }
- } else {
- let axis = this.config.x.type === 'ordinal' ||
- (this.config.x.type === 'linear' && this.config.x.bin)
- ? 'y'
- : 'x';
- test.forEach(e => (e.total = e.values[axis]));
- }
-
- if (
- (this.config.x.sort === 'total-ascending' && this.config.x.type == 'ordinal') ||
- (this.config.y.sort === 'total-descending' && this.config.y.type == 'ordinal')
- ) {
- totalOrder = test.sort((a, b) => ascending(a.total, b.total)).map(m => m.key);
- } else if (
- (this.config.x.sort === 'total-descending' && this.config.x.type == 'ordinal') ||
- (this.config.y.sort === 'total-ascending' && this.config.y.type == 'ordinal')
- ) {
- totalOrder = test.sort((a, b) => descending(+a.total, +b.total)).map(m => m.key);
- }
-
- return { nested: test, dom_x: dom_x, dom_y: dom_y, totalOrder: totalOrder };
-}
diff --git a/src/chart/resize/updateDataMarks/drawArea.js b/src/chart/drawArea.js
similarity index 100%
rename from src/chart/resize/updateDataMarks/drawArea.js
rename to src/chart/drawArea.js
diff --git a/src/chart/resize/updateDataMarks/drawBars.js b/src/chart/drawBars.js
similarity index 99%
rename from src/chart/resize/updateDataMarks/drawBars.js
rename to src/chart/drawBars.js
index bfd8bb2..8384479 100644
--- a/src/chart/resize/updateDataMarks/drawBars.js
+++ b/src/chart/drawBars.js
@@ -60,7 +60,7 @@ export default function drawBars(marks) {
bars.each(function(d) {
let mark = select(this.parentNode.parentNode).datum();
d.tooltip = mark.tooltip;
- d.arrange = mark.split && mark.arrange ? mark.arrange : mark.split ? 'grouped' : null;
+ d.arrange = mark.split ? mark.arrange : null;
d.subcats = config.legend.order
? config.legend.order.slice().reverse()
: mark.values && mark.values[mark.split]
@@ -163,7 +163,6 @@ export default function drawBars(marks) {
? mark.values[mark.split]
: set(rawData.map(m => m[mark.split])).values();
d.tooltip = mark.tooltip;
- select(this).attr(mark.attributes);
});
let xformat = config.marks.map(m => m.summarizeX === 'percent').indexOf(true) > -1
diff --git a/src/chart/resize/drawGridlines.js b/src/chart/drawGridlines.js
similarity index 100%
rename from src/chart/resize/drawGridlines.js
rename to src/chart/drawGridlines.js
diff --git a/src/chart/resize/updateDataMarks/drawLines.js b/src/chart/drawLines.js
similarity index 100%
rename from src/chart/resize/updateDataMarks/drawLines.js
rename to src/chart/drawLines.js
diff --git a/src/chart/resize/updateDataMarks/drawPoints.js b/src/chart/drawPoints.js
similarity index 100%
rename from src/chart/resize/updateDataMarks/drawPoints.js
rename to src/chart/drawPoints.js
diff --git a/src/chart/resize/updateDataMarks/drawText.js b/src/chart/drawText.js
similarity index 100%
rename from src/chart/resize/updateDataMarks/drawText.js
rename to src/chart/drawText.js
diff --git a/src/chart/index.js b/src/chart/index.js
index ea453ad..0f1c897 100644
--- a/src/chart/index.js
+++ b/src/chart/index.js
@@ -1,29 +1,25 @@
+import checkRequired from './checkRequired';
+import consolidateData from './consolidateData';
+import destroy from './destroy';
+import draw from './draw';
+import drawArea from './drawArea';
+import drawBars from './drawBars';
+import drawGridlines from './drawGridlines';
+import drawLines from './drawLines';
+import drawPoints from './drawPoints';
+import drawText from './drawText';
import init from './init';
-import checkRequired from './init/checkRequired';
-
import layout from './layout';
-
-import draw from './draw';
-import consolidateData from './draw/consolidateData';
-import setDefaults from './draw/consolidateData/setDefaults';
-import transformData from './draw/consolidateData/transformData';
-import setColorScale from './draw/setColorScale';
-import xScaleAxis from './draw/xScaleAxis';
-import yScaleAxis from './draw/yScaleAxis';
-
+import makeLegend from './makeLegend';
import resize from './resize';
-import textSize from './resize/textSize';
-import setMargins from './resize/setMargins';
-import drawGridlines from './resize/drawGridlines';
-import makeLegend from './resize/makeLegend';
-import updateDataMarks from './resize/updateDataMarks';
-import drawArea from './resize/updateDataMarks/drawArea';
-import drawBars from './resize/updateDataMarks/drawBars';
-import drawLines from './resize/updateDataMarks/drawLines';
-import drawPoints from './resize/updateDataMarks/drawPoints';
-import drawText from './resize/updateDataMarks/drawText';
-
-import destroy from './destroy';
+import setColorScale from './setColorScale';
+import setDefaults from './setDefaults';
+import setMargins from './setMargins';
+import textSize from './textSize';
+import transformData from './transformData';
+import updateDataMarks from './updateDataMarks';
+import xScaleAxis from './xScaleAxis';
+import yScaleAxis from './yScaleAxis';
const chartProto = {
raw_data: [],
diff --git a/src/chart/layout.js b/src/chart/layout.js
index aa14740..2b775ce 100644
--- a/src/chart/layout.js
+++ b/src/chart/layout.js
@@ -55,14 +55,12 @@ export default function layout() {
.attr('fill', 'none')
.style('pointer-events', 'all');
//add legend
- if (!this.parent)
- this.wrap
- .append('ul')
- .datum(() => null) // prevent data inheritance
- .attr('class', 'legend')
- .style('vertical-align', 'top')
- .append('span')
- .attr('class', 'legend-title');
+ const legend = this.wrap.append('ul').datum(() => null); // prevent data inheritance
+ legend
+ .attr('class', 'legend')
+ .style('vertical-align', 'top')
+ .append('span')
+ .attr('class', 'legend-title');
select(this.div).select('.loader').remove();
diff --git a/src/chart/resize/makeLegend.js b/src/chart/makeLegend.js
similarity index 77%
rename from src/chart/resize/makeLegend.js
rename to src/chart/makeLegend.js
index e83d936..1efaf8d 100644
--- a/src/chart/resize/makeLegend.js
+++ b/src/chart/makeLegend.js
@@ -16,24 +16,11 @@ export default function makeLegend(scale = this.colorScale, label = '', custom_d
let legendOriginal = this.legend || this.wrap.select('.legend');
let legend = legendOriginal;
- if (!this.parent) {
- //singular chart
- if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
- this.wrap.node().insertBefore(legendOriginal.node(), this.svg.node().parentNode);
- } else {
- this.wrap.node().appendChild(legendOriginal.node());
- }
+ if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
+ this.wrap.node().insertBefore(legendOriginal.node(), this.svg.node().parentNode);
} else {
- //multiples - keep legend outside of individual charts' wraps
- if (this.config.legend.location === 'top' || this.config.legend.location === 'left') {
- this.parent.wrap
- .node()
- .insertBefore(legendOriginal.node(), this.parent.wrap.select('.wc-chart').node());
- } else {
- this.parent.wrap.node().appendChild(legendOriginal.node());
- }
+ this.wrap.node().appendChild(legendOriginal.node());
}
-
legend.style('padding', 0);
let legend_data =
@@ -84,7 +71,9 @@ export default function makeLegend(scale = this.colorScale, label = '', custom_d
leg_parts.selectAll('.legend-color-block').each(function(e) {
let svg = select(this);
if (e.mark === 'circle') {
- svg.append('circle').attr({ cx: '.5em', cy: '.5em', r: '.45em', class: 'legend-mark' });
+ svg
+ .append('circle')
+ .attr({ cx: '.5em', cy: '.45em', r: '.45em', class: 'legend-mark' });
} else if (e.mark === 'line') {
svg.append('line').attr({
x1: 0,
@@ -120,9 +109,8 @@ export default function makeLegend(scale = this.colorScale, label = '', custom_d
.text(d => d.label);
if (scale.domain().length > 0) {
- const legendDisplay = (this.config.legend.location === 'bottom' ||
- this.config.legend.location === 'top') &&
- !this.parent
+ const legendDisplay = this.config.legend.location === 'bottom' ||
+ this.config.legend.location === 'top'
? 'block'
: 'inline-block';
legend.style('display', legendDisplay);
diff --git a/src/chart/resize.js b/src/chart/resize.js
index c22f3c0..d887139 100644
--- a/src/chart/resize.js
+++ b/src/chart/resize.js
@@ -14,13 +14,13 @@ export default function resize() {
this.margin = this.setMargins();
- let svg_width = config.x.type === 'ordinal' && +config.x.range_band
+ let svg_width = config.x.type === 'ordinal' && +config.range_band
? this.raw_width + this.margin.left + this.margin.right
: !config.resizable
? this.raw_width
: !config.max_width || div_width < config.max_width ? div_width : this.raw_width;
this.plot_width = svg_width - this.margin.left - this.margin.right;
- var svg_height = config.y.type === 'ordinal' && +config.y.range_band
+ var svg_height = config.y.type === 'ordinal' && +config.range_band
? this.raw_height + this.margin.top + this.margin.bottom
: !config.resizable && config.height
? config.height
@@ -75,7 +75,6 @@ export default function resize() {
.attr({ stroke: '#eee', 'stroke-width': 1, 'shape-rendering': 'crispEdges' });
this.drawGridlines();
-
//update legend - margins need to be set first
this.makeLegend();
diff --git a/src/chart/draw/setColorScale.js b/src/chart/setColorScale.js
similarity index 92%
rename from src/chart/draw/setColorScale.js
rename to src/chart/setColorScale.js
index eb9ac71..4db2362 100644
--- a/src/chart/draw/setColorScale.js
+++ b/src/chart/setColorScale.js
@@ -1,4 +1,4 @@
-import naturalSorter from '../../dataOps/naturalSorter';
+import naturalSorter from '../dataOps/naturalSorter';
import { set, ascending, scale } from 'd3';
export default function setColorScale() {
diff --git a/src/chart/draw/consolidateData/setDefaults.js b/src/chart/setDefaults.js
similarity index 92%
rename from src/chart/draw/consolidateData/setDefaults.js
rename to src/chart/setDefaults.js
index 9c4d85f..90f4a5d 100644
--- a/src/chart/draw/consolidateData/setDefaults.js
+++ b/src/chart/setDefaults.js
@@ -15,9 +15,6 @@ export default function setDefaults() {
this.config.x.type = this.config.x.type || 'linear';
this.config.y.type = this.config.y.type || 'linear';
- this.config.x.range_band = this.config.x.range_band || this.config.range_band;
- this.config.y.range_band = this.config.y.range_band || this.config.range_band;
-
this.config.margin = this.config.margin || {};
this.config.legend = this.config.legend || {};
this.config.legend.label = this.config.legend.label !== undefined
diff --git a/src/chart/resize/setMargins.js b/src/chart/setMargins.js
similarity index 100%
rename from src/chart/resize/setMargins.js
rename to src/chart/setMargins.js
diff --git a/src/chart/resize/textSize.js b/src/chart/textSize.js
similarity index 100%
rename from src/chart/resize/textSize.js
rename to src/chart/textSize.js
diff --git a/src/chart/transformData.js b/src/chart/transformData.js
new file mode 100644
index 0000000..a123f52
--- /dev/null
+++ b/src/chart/transformData.js
@@ -0,0 +1,392 @@
+import naturalSorter from '../dataOps/naturalSorter';
+import summarize from '../dataOps/summarize';
+import {
+ time,
+ sum,
+ set,
+ extent,
+ merge,
+ nest,
+ scale,
+ range,
+ ascending,
+ descending,
+ quantile,
+ max
+} from 'd3';
+
+//////////////////////////////////////////////////////////
+// transformData(raw, mark) provides specifications and data for
+// each set of marks. As such, it is called once for each
+// item specified in the config.marks array.
+//
+// parameters
+// raw - the raw data for use in the mark. Filters from controls
+// are typically already applied.
+// mark - a single mark object from config.marks
+////////////////////////////////////////////////////////
+
+export default function transformData(raw, mark) {
+ //convenience mappings
+ let config = this.config;
+ let x_behavior = config.x.behavior || 'raw';
+ let y_behavior = config.y.behavior || 'raw';
+ let sublevel = mark.type === 'line'
+ ? config.x.column
+ : mark.type === 'bar' && mark.split ? mark.split : null;
+ let dateConvert = time.format(config.date_format);
+ let totalOrder;
+
+ ///////////////////////////////////////////////
+ // calcStartTotal() - method to calculate percentages in bars
+ //////////////////////////////////////////////
+ function calcStartTotal(e) {
+ let axis = config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)
+ ? 'y'
+ : 'x';
+ e.total = sum(e.values.map(m => +m.values[axis]));
+ let counter = 0;
+ e.values.forEach((v, i) => {
+ if (config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)) {
+ v.values.y = mark.summarizeY === 'percent' ? v.values.y / e.total : v.values.y || 0;
+ counter += +v.values.y;
+ v.values.start = e.values[i - 1] ? counter : v.values.y;
+ } else {
+ v.values.x = mark.summarizeX === 'percent' ? v.values.x / e.total : v.values.x || 0;
+ v.values.start = counter;
+ counter += +v.values.x;
+ }
+ });
+ }
+
+ function makeNest(entries, sublevel) {
+ let dom_xs = [];
+ let dom_ys = [];
+ let this_nest = nest();
+
+ if (
+ (config.x.type === 'linear' && config.x.bin) ||
+ (config.y.type === 'linear' && config.y.bin)
+ ) {
+ let xy = config.x.type === 'linear' && config.x.bin ? 'x' : 'y';
+ let quant = scale
+ .quantile()
+ .domain(extent(entries.map(m => +m[config[xy].column])))
+ .range(range(+config[xy].bin));
+
+ entries.forEach(e => (e.wc_bin = quant(e[config[xy].column])));
+
+ this_nest.key(d => quant.invertExtent(d.wc_bin));
+ } else {
+ this_nest.key(d => mark.per.map(m => d[m]).join(' '));
+ }
+
+ if (sublevel) {
+ this_nest.key(d => d[sublevel]);
+ this_nest.sortKeys((a, b) => {
+ return config.x.type === 'time'
+ ? ascending(new Date(a), new Date(b))
+ : config.x.order
+ ? ascending(config.x.order.indexOf(a), config.x.order.indexOf(b))
+ : sublevel === config.color_by && config.legend.order
+ ? ascending(config.legend.order.indexOf(a), config.legend.order.indexOf(b))
+ : config.x.type === 'ordinal' || config.y.type === 'ordinal'
+ ? naturalSorter(a, b)
+ : ascending(+a, +b);
+ });
+ }
+ this_nest.rollup(r => {
+ let obj = { raw: r };
+ let y_vals = r.map(m => m[config.y.column]).sort(ascending);
+ let x_vals = r.map(m => m[config.x.column]).sort(ascending);
+ obj.x = config.x.type === 'ordinal'
+ ? r[0][config.x.column]
+ : summarize(x_vals, mark.summarizeX);
+ obj.y = config.y.type === 'ordinal'
+ ? r[0][config.y.column]
+ : summarize(y_vals, mark.summarizeY);
+
+ obj.x_q25 = config.error_bars && config.y.type === 'ordinal'
+ ? quantile(x_vals, 0.25)
+ : obj.x;
+ obj.x_q75 = config.error_bars && config.y.type === 'ordinal'
+ ? quantile(x_vals, 0.75)
+ : obj.x;
+ obj.y_q25 = config.error_bars ? quantile(y_vals, 0.25) : obj.y;
+ obj.y_q75 = config.error_bars ? quantile(y_vals, 0.75) : obj.y;
+ dom_xs.push([obj.x_q25, obj.x_q75, obj.x]);
+ dom_ys.push([obj.y_q25, obj.y_q75, obj.y]);
+
+ if (mark.summarizeY === 'cumulative') {
+ let interm = entries.filter(f => {
+ return config.x.type === 'time'
+ ? new Date(f[config.x.column]) <= new Date(r[0][config.x.column])
+ : +f[config.x.column] <= +r[0][config.x.column];
+ });
+ if (mark.per.length) {
+ interm = interm.filter(f => f[mark.per[0]] === r[0][mark.per[0]]);
+ }
+
+ let cumul = config.x.type === 'time'
+ ? interm.length
+ : sum(
+ interm.map(
+ m =>
+ +m[config.y.column] || +m[config.y.column] === 0
+ ? +m[config.y.column]
+ : 1
+ )
+ );
+ dom_ys.push([cumul]);
+ obj.y = cumul;
+ }
+ if (mark.summarizeX === 'cumulative') {
+ let interm = entries.filter(f => {
+ return config.y.type === 'time'
+ ? new Date(f[config.y.column]) <= new Date(r[0][config.y.column])
+ : +f[config.y.column] <= +r[0][config.y.column];
+ });
+ if (mark.per.length) {
+ interm = interm.filter(f => f[mark.per[0]] === r[0][mark.per[0]]);
+ }
+ dom_xs.push([interm.length]);
+ obj.x = interm.length;
+ }
+
+ return obj;
+ });
+
+ let test = this_nest.entries(entries);
+
+ let dom_x = extent(merge(dom_xs));
+ let dom_y = extent(merge(dom_ys));
+
+ if (sublevel && mark.type === 'bar' && mark.arrange === 'stacked') {
+ test.forEach(calcStartTotal);
+ if (config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)) {
+ dom_y = extent(test.map(m => m.total));
+ }
+ if (config.y.type === 'ordinal' || (config.y.type === 'linear' && config.y.bin)) {
+ dom_x = extent(test.map(m => m.total));
+ }
+ } else if (sublevel && mark.type === 'bar' && mark.split) {
+ test.forEach(calcStartTotal);
+ } else {
+ let axis = config.x.type === 'ordinal' || (config.x.type === 'linear' && config.x.bin)
+ ? 'y'
+ : 'x';
+ test.forEach(e => (e.total = e.values[axis]));
+ }
+
+ if (
+ (config.x.sort === 'total-ascending' && config.x.type == 'ordinal') ||
+ (config.y.sort === 'total-descending' && config.y.type == 'ordinal')
+ ) {
+ totalOrder = test.sort((a, b) => ascending(a.total, b.total)).map(m => m.key);
+ } else if (
+ (config.x.sort === 'total-descending' && config.x.type == 'ordinal') ||
+ (config.y.sort === 'total-ascending' && config.y.type == 'ordinal')
+ ) {
+ totalOrder = test.sort((a, b) => descending(+a.total, +b.total)).map(m => m.key);
+ }
+
+ return { nested: test, dom_x: dom_x, dom_y: dom_y };
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DATA PREP
+ // prepare data based on the properties of the mark - drop missing records, etc
+ //////////////////////////////////////////////////////////////////////////////////
+
+ // only use data for the current mark
+ raw = mark.per && mark.per.length ? raw.filter(f => f[mark.per[0]]) : raw;
+
+ // Make sure data has x and y values
+ if (config.x.column) {
+ raw = raw.filter(f => f[config.x.column] !== undefined);
+ }
+ if (config.y.column) {
+ raw = raw.filter(f => f[config.y.column] !== undefined);
+ }
+
+ //check that x and y have the correct formats
+ if (config.x.type === 'time') {
+ raw = raw.filter(
+ f =>
+ f[config.x.column] instanceof Date
+ ? f[config.x.column]
+ : dateConvert.parse(f[config.x.column])
+ );
+ raw.forEach(
+ e =>
+ (e[config.x.column] = e[config.x.column] instanceof Date
+ ? e[config.x.column]
+ : dateConvert.parse(e[config.x.column]))
+ );
+ }
+ if (config.y.type === 'time') {
+ raw = raw.filter(
+ f =>
+ f[config.y.column] instanceof Date
+ ? f[config.y.column]
+ : dateConvert.parse(f[config.y.column])
+ );
+ raw.forEach(
+ e =>
+ (e[config.y.column] = e[config.y.column] instanceof Date
+ ? e[config.y.column]
+ : dateConvert.parse(e[config.y.column]))
+ );
+ }
+
+ if ((config.x.type === 'linear' || config.x.type === 'log') && config.x.column) {
+ raw = raw.filter(f => {
+ return mark.summarizeX !== 'count' && mark.summarizeX !== 'percent'
+ ? +f[config.x.column] || +f[config.x.column] === 0
+ : f;
+ });
+ }
+ if ((config.y.type === 'linear' || config.y.type === 'log') && config.y.column) {
+ raw = raw.filter(f => {
+ return mark.summarizeY !== 'count' && mark.summarizeY !== 'percent'
+ ? +f[config.y.column] || +f[config.y.column] === 0
+ : f;
+ });
+ }
+
+ //prepare nested data required for bar charts
+ let raw_nest;
+ if (mark.type === 'bar') {
+ raw_nest = mark.arrange !== 'stacked' ? makeNest(raw, sublevel) : makeNest(raw);
+ } else if (mark.summarizeX === 'count' || mark.summarizeY === 'count') {
+ raw_nest = makeNest(raw);
+ }
+
+ // Get the domain for the mark based on the raw data
+ let raw_dom_x = mark.summarizeX === 'cumulative'
+ ? [0, raw.length]
+ : config.x.type === 'ordinal'
+ ? set(raw.map(m => m[config.x.column])).values().filter(f => f)
+ : mark.split && mark.arrange !== 'stacked'
+ ? extent(merge(raw_nest.nested.map(m => m.values.map(p => p.values.raw.length))))
+ : mark.summarizeX === 'count'
+ ? extent(raw_nest.nested.map(m => m.values.raw.length))
+ : extent(raw.map(m => +m[config.x.column]).filter(f => +f || +f === 0));
+
+ let raw_dom_y = mark.summarizeY === 'cumulative'
+ ? [0, raw.length]
+ : config.y.type === 'ordinal'
+ ? set(raw.map(m => m[config.y.column])).values().filter(f => f)
+ : mark.split && mark.arrange !== 'stacked'
+ ? extent(merge(raw_nest.nested.map(m => m.values.map(p => p.values.raw.length))))
+ : mark.summarizeY === 'count'
+ ? extent(raw_nest.nested.map(m => m.values.raw.length))
+ : extent(raw.map(m => +m[config.y.column]).filter(f => +f || +f === 0));
+
+ let filtered = raw;
+
+ let filt1_xs = [];
+ let filt1_ys = [];
+ if (this.filters.length) {
+ this.filters.forEach(e => {
+ filtered = filtered.filter(d => {
+ return e.val === 'All'
+ ? d
+ : e.val instanceof Array ? e.val.indexOf(d[e.col]) > -1 : d[e.col] === e.val;
+ });
+ });
+ //get domain for all non-All values of first filter
+ if (config.x.behavior === 'firstfilter' || config.y.behavior === 'firstfilter') {
+ this.filters[0].choices.filter(f => f !== 'All').forEach(e => {
+ let perfilter = raw.filter(f => f[this.filters[0].col] === e);
+ let filt_nested = makeNest(perfilter, sublevel);
+ filt1_xs.push(filt_nested.dom_x);
+ filt1_ys.push(filt_nested.dom_y);
+ });
+ }
+ }
+
+ //filter on mark-specific instructions
+ if (mark.values) {
+ for (let a in mark.values) {
+ filtered = filtered.filter(f => {
+ return mark.values[a].indexOf(f[a]) > -1;
+ });
+ }
+ }
+ let filt1_dom_x = extent(merge(filt1_xs));
+ let filt1_dom_y = extent(merge(filt1_ys));
+
+ let current_nested = makeNest(filtered, sublevel);
+
+ let flex_dom_x = current_nested.dom_x;
+ let flex_dom_y = current_nested.dom_y;
+
+ if (mark.type === 'bar') {
+ if (config.y.type === 'ordinal' && mark.summarizeX === 'count') {
+ config.x.domain = config.x.domain ? [0, config.x.domain[1]] : [0, null];
+ } else if (config.x.type === 'ordinal' && mark.summarizeY === 'count') {
+ config.y.domain = config.y.domain ? [0, config.y.domain[1]] : [0, null];
+ }
+ }
+
+ //several criteria must be met in order to use the 'firstfilter' domain
+ let nonall = Boolean(
+ this.filters.length &&
+ this.filters[0].val !== 'All' &&
+ this.filters.slice(1).filter(f => f.val === 'All').length === this.filters.length - 1
+ );
+
+ let pre_x_dom = !this.filters.length
+ ? flex_dom_x
+ : x_behavior === 'raw'
+ ? raw_dom_x
+ : nonall && x_behavior === 'firstfilter' ? filt1_dom_x : flex_dom_x;
+ let pre_y_dom = !this.filters.length
+ ? flex_dom_y
+ : y_behavior === 'raw'
+ ? raw_dom_y
+ : nonall && y_behavior === 'firstfilter' ? filt1_dom_y : flex_dom_y;
+
+ let x_dom = config.x_dom
+ ? config.x_dom
+ : config.x.type === 'ordinal' && config.x.behavior === 'flex'
+ ? set(filtered.map(m => m[config.x.column])).values()
+ : config.x.type === 'ordinal'
+ ? set(raw.map(m => m[config.x.column])).values()
+ : config.x_from0 ? [0, max(pre_x_dom)] : pre_x_dom;
+
+ let y_dom = config.y_dom
+ ? config.y_dom
+ : config.y.type === 'ordinal' && config.y.behavior === 'flex'
+ ? set(filtered.map(m => m[config.y.column])).values()
+ : config.y.type === 'ordinal'
+ ? set(raw.map(m => m[config.y.column])).values()
+ : config.y_from0 ? [0, max(pre_y_dom)] : pre_y_dom;
+
+ if (config.x.domain && (config.x.domain[0] || config.x.domain[0] === 0)) {
+ x_dom[0] = config.x.domain[0];
+ }
+ if (config.x.domain && (config.x.domain[1] || config.x.domain[1] === 0)) {
+ x_dom[1] = config.x.domain[1];
+ }
+ if (config.y.domain && (config.y.domain[0] || config.y.domain[0] === 0)) {
+ y_dom[0] = config.y.domain[0];
+ }
+ if (config.y.domain && (config.y.domain[1] || config.y.domain[1] === 0)) {
+ y_dom[1] = config.y.domain[1];
+ }
+
+ if (config.x.type === 'ordinal' && !config.x.order) {
+ config.x.order = totalOrder;
+ }
+ if (config.y.type === 'ordinal' && !config.y.order) {
+ config.y.order = totalOrder;
+ }
+
+ this.current_data = current_nested.nested;
+
+ this.events.onDatatransform.call(this);
+
+ return { config: mark, data: current_nested.nested, x_dom: x_dom, y_dom: y_dom };
+}
diff --git a/src/chart/resize/updateDataMarks.js b/src/chart/updateDataMarks.js
similarity index 100%
rename from src/chart/resize/updateDataMarks.js
rename to src/chart/updateDataMarks.js
diff --git a/src/chart/draw/xScaleAxis.js b/src/chart/xScaleAxis.js
similarity index 100%
rename from src/chart/draw/xScaleAxis.js
rename to src/chart/xScaleAxis.js
diff --git a/src/chart/draw/yScaleAxis.js b/src/chart/yScaleAxis.js
similarity index 100%
rename from src/chart/draw/yScaleAxis.js
rename to src/chart/yScaleAxis.js
diff --git a/src/createTable.js b/src/createTable.js
index 523af57..252f4e8 100644
--- a/src/createTable.js
+++ b/src/createTable.js
@@ -14,18 +14,28 @@ export default function createTable(element = 'body', config = {}, controls = nu
thisTable.required_cols = [];
- thisTable.wrap = select(thisTable.div).append('div').datum(thisTable);
+ thisTable.wrap = select(thisTable.div).append('div');
thisTable.events = {
onInit() {},
onLayout() {},
onPreprocess() {},
+ onDatatransform() {},
onDraw() {},
+ onResize() {},
onDestroy() {}
};
thisTable.on = function(event, callback) {
- let possible_events = ['init', 'layout', 'preprocess', 'draw', 'destroy'];
+ let possible_events = [
+ 'init',
+ 'layout',
+ 'preprocess',
+ 'datatransform',
+ 'draw',
+ 'resize',
+ 'destroy'
+ ];
if (possible_events.indexOf(event) < 0) {
return;
}
diff --git a/src/multiply.js b/src/multiply.js
index c6e6121..85a0f12 100644
--- a/src/multiply.js
+++ b/src/multiply.js
@@ -2,13 +2,9 @@ import createChart from './createChart';
import { set, ascending } from 'd3';
export default function multiply(chart, data, split_by, order, test = false) {
- chart.wrap.classed('wc-layout wc-small-multiples', true).classed('wc-chart', false);
-
- //Define container for legend that overrides multiples' legends.
- chart.master_legend = chart.wrap.append('ul').attr('class', 'legend');
- chart.master_legend.append('span').classed('legend-title', true);
-
- //Instantiate multiples array.
+ let config = chart.config;
+ let wrap = chart.wrap.classed('wc-layout wc-small-multiples', true).classed('wc-chart', false);
+ let master_legend = wrap.append('ul').attr('class', 'legend');
chart.multiples = [];
function goAhead(data) {
@@ -17,16 +13,15 @@ export default function multiply(chart, data, split_by, order, test = false) {
split_vals = split_vals.sort((a, b) => ascending(order.indexOf(a), order.indexOf(b)));
}
split_vals.forEach(e => {
- var mchart = createChart(chart.wrap.node(), chart.config, chart.controls);
+ var mchart = createChart(chart.wrap.node(), config, chart.controls);
chart.multiples.push(mchart);
mchart.parent = chart;
mchart.events = chart.events;
- mchart.legend = chart.master_legend;
+ mchart.legend = master_legend;
mchart.filters.unshift({ col: split_by, val: e, choices: split_vals });
mchart.wrap.insert('span', 'svg').attr('class', 'wc-chart-title').text(e);
mchart.init(data, test);
});
}
-
goAhead(data);
}
diff --git a/src/table/draw.js b/src/table/draw.js
index 80fa2b1..d4d3ffc 100644
--- a/src/table/draw.js
+++ b/src/table/draw.js
@@ -1,48 +1,75 @@
import applyFilters from './draw/applyFilters';
-import updateDataObject from './draw/updateDataObject';
import applySearchTerm from './draw/applySearchTerm';
-import checkFilters from './draw/checkFilters';
-import updateTableHeaders from './draw/updateTableHeaders';
+import '../util/array-equals';
import clone from '../util/clone';
-import drawTableBody from './draw/drawTableBody';
-import dynamicLayout from './draw/dynamicLayout';
+import { select } from 'd3';
export default function draw(passed_data) {
- const table = this;
- const config = this.config;
+ const context = this,
+ config = this.config,
+ table = this.table;
- this.data.passed = passed_data; // make passed data available on preprocess
- this.events.onPreprocess.call(this);
-
- if (!passed_data)
- //Apply filters if data is not passed to table.draw().
+ //Apply filters if data is not passed to table.draw().
+ if (!passed_data) {
applyFilters.call(this);
- else
+ } else {
//Otherwise update data object.
- updateDataObject.call(this);
+ this.data.raw = passed_data;
+ this.data.filtered = passed_data;
+ this.config.activePage = 0;
+ this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
+ this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
+ }
//Compare current filter settings to previous filter settings, if any.
- checkFilters.call(this);
+ if (this.filters) {
+ this.currentFilters = this.filters.map(filter => filter.val);
+
+ //Reset pagination if filters have changed.
+ if (!this.currentFilters.equals(this.previousFilters)) {
+ this.config.activePage = 0;
+ this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
+ this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
+ }
+
+ this.previousFilters = this.currentFilters;
+ }
+
+ let data;
//Filter data on search term if it exists and set data to searched data.
- applySearchTerm.call(this);
+ if (this.searchable.searchTerm) {
+ applySearchTerm.call(this);
+ data = this.data.searched;
+ } else {
+ //Otherwise delete previously searched data and set data to filtered data.
+ delete this.data.searched;
+ data = this.data.filtered;
+ }
this.searchable.wrap
.select('.nNrecords')
.text(
- this.data.processing.length === this.data.raw.length
+ data.length === this.data.raw.length
? `${this.data.raw.length} records displayed`
- : `${this.data.processing.length}/${this.data.raw.length} records displayed`
+ : `${data.length}/${this.data.raw.length} records displayed`
);
- //Update table headers.
- updateTableHeaders.call(this);
+ //update table header
+ this.thead_cells = this.thead.select('tr').selectAll('th').data(this.config.headers, d => d);
+ this.thead_cells.exit().remove();
+ this.thead_cells.enter().append('th');
+
+ this.thead_cells
+ .sort((a, b) => this.config.headers.indexOf(a) - this.config.headers.indexOf(b))
+ .attr('class', d => this.config.cols[this.config.headers.indexOf(d)]) // associate column header with column name
+ .text(d => d);
//Clear table body rows.
this.tbody.selectAll('tr').remove();
//Print a note that no data was selected for empty tables.
- if (this.data.processing.length === 0) {
+ if (data.length === 0) {
this.tbody
.append('tr')
.classed('no-data', true)
@@ -50,54 +77,110 @@ export default function draw(passed_data) {
.attr('colspan', this.config.cols.length)
.text('No data selected.');
- //Bind table filtered/searched data to table container.
- this.data.current = clone(this.data.processing);
- this.table.datum(this.table.current);
-
//Add export.
if (this.config.exportable)
this.config.exports.forEach(fmt => {
- this.exportable.exports[fmt].call(this, this.data.processing);
+ this.exportable.exports[fmt].call(this, data);
});
//Add pagination.
- if (this.config.pagination) this.pagination.addPagination.call(this, this.data.processing);
+ if (this.config.pagination) this.pagination.addPagination.call(this, data);
} else {
//Sort data.
if (this.config.sortable) {
this.thead.selectAll('th').on('click', function(header) {
- table.sortable.onClick.call(table, this, header);
+ context.sortable.onClick.call(context, this, header);
});
- if (this.sortable.order.length) this.sortable.sortData.call(this, this.data.processing);
+ if (this.sortable.order.length) this.sortable.sortData.call(this, data);
}
//Bind table filtered/searched data to table container.
- this.data.current = clone(this.data.processing);
- this.table.datum(this.data.current);
+ this.wrap.datum(clone(data));
//Add export.
if (this.config.exportable)
this.config.exports.forEach(fmt => {
- this.exportable.exports[fmt].call(this, this.data.processing);
+ this.exportable.exports[fmt].call(this, data);
});
//Add pagination.
if (this.config.pagination) {
- this.pagination.addPagination.call(this, this.data.processing);
+ this.pagination.addPagination.call(this, data);
//Apply pagination.
- this.data.processing = this.data.processing.filter(
- (d, i) => this.config.startIndex <= i && i < this.config.endIndex
- );
+ data = data.filter((d, i) => this.config.startIndex <= i && i < this.config.endIndex);
}
//Define table body rows.
- drawTableBody.call(this);
+ const rows = this.tbody.selectAll('tr').data(data).enter().append('tr');
+
+ //Define table body cells.
+ const cells = rows.selectAll('td').data(d =>
+ this.config.cols.map(key => {
+ return { col: key, text: d[key] };
+ })
+ );
+ cells.exit().remove();
+ cells.enter().append('td');
+ cells
+ .sort((a, b) => this.config.cols.indexOf(a.col) - this.config.cols.indexOf(b.col))
+ .attr('class', d => d.col)
+ .each(function(d) {
+ const cell = select(this);
+
+ //Apply text in data as html or as plain text.
+ if (config.as_html) {
+ cell.html(d.text);
+ } else {
+ cell.text(d.text);
+ }
+ });
}
//Alter table layout if table is narrower than table top or bottom.
- dynamicLayout.call(this);
+ const widths = {
+ table: this.table.select('thead').node().offsetWidth,
+ top:
+ this.wrap.select('.table-top .searchable-container').node().offsetWidth +
+ this.wrap.select('.table-top .sortable-container').node().offsetWidth,
+ bottom:
+ this.wrap.select('.table-bottom .pagination-container').node().offsetWidth +
+ this.wrap.select('.table-bottom .exportable-container').node().offsetWidth
+ };
+
+ if (widths.table < Math.max(widths.top, widths.bottom) && this.config.layout === 'horizontal') {
+ this.config.layout = 'vertical';
+ this.wrap
+ .style('display', 'inline-block')
+ .selectAll('.table-top,.table-bottom')
+ .style('display', 'inline-block')
+ .selectAll('.interactivity')
+ .style({
+ display: 'block',
+ clear: 'both'
+ });
+ } else if (
+ widths.table >= Math.max(widths.top, widths.bottom) &&
+ this.config.layout === 'vertical'
+ ) {
+ this.config.layout = 'horizontal';
+ this.wrap
+ .style('display', 'table')
+ .selectAll('.table-top,.table-bottom')
+ .style('display', 'block')
+ .selectAll('.interactivity')
+ .style({
+ display: 'inline-block',
+ float: function() {
+ return select(this).classed('searchable-container') ||
+ select(this).classed('pagination-container')
+ ? 'right'
+ : null;
+ },
+ clear: null
+ });
+ }
this.events.onDraw.call(this);
}
diff --git a/src/table/draw/applySearchTerm.js b/src/table/draw/applySearchTerm.js
index 9caaa00..16fe8ec 100644
--- a/src/table/draw/applySearchTerm.js
+++ b/src/table/draw/applySearchTerm.js
@@ -1,22 +1,15 @@
-export default function applySearchTerm(data) {
- if (this.searchable.searchTerm) {
- //Determine which rows contain input text.
- this.data.searched = this.data.filtered.filter(d => {
- let match = false;
+export default function applySearchTerm() {
+ //Determine which rows contain input text.
+ this.data.searched = this.data.filtered.filter(d => {
+ let match = false;
- Object.keys(d).filter(key => this.config.cols.indexOf(key) > -1).forEach(var_name => {
- if (match === false) {
- const cellText = '' + d[var_name];
- match = cellText.toLowerCase().indexOf(this.searchable.searchTerm) > -1;
- }
- });
-
- return match;
+ Object.keys(d).filter(key => this.config.cols.indexOf(key) > -1).forEach(var_name => {
+ if (match === false) {
+ const cellText = '' + d[var_name];
+ match = cellText.toLowerCase().indexOf(this.searchable.searchTerm) > -1;
+ }
});
- this.data.processing = this.data.searched;
- } else {
- //Otherwise delete previously searched data and set data to filtered data.
- delete this.data.searched;
- this.data.processing = this.data.filtered;
- }
+
+ return match;
+ });
}
diff --git a/src/table/draw/checkFilters.js b/src/table/draw/checkFilters.js
deleted file mode 100644
index db9043d..0000000
--- a/src/table/draw/checkFilters.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import '../../util/array-equals';
-
-export default function checkFilters() {
- if (this.filters) {
- this.currentFilters = this.filters.map(filter => filter.val);
-
- //Reset pagination if filters have changed.
- if (!this.currentFilters.equals(this.previousFilters)) {
- this.config.activePage = 0;
- this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
- this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
- }
-
- this.previousFilters = this.currentFilters;
- }
-}
diff --git a/src/table/draw/drawTableBody.js b/src/table/draw/drawTableBody.js
deleted file mode 100644
index a6fea92..0000000
--- a/src/table/draw/drawTableBody.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { select } from 'd3';
-
-export default function drawTableBody() {
- const table = this;
-
- //Define table body rows.
- const rows = this.tbody.selectAll('tr').data(this.data.processing).enter().append('tr');
-
- //Define table body cells.
- const cells = rows.selectAll('td').data(d =>
- this.config.cols.map(key => {
- return { col: key, text: d[key] };
- })
- );
- cells.exit().remove();
- cells.enter().append('td');
- cells
- .sort((a, b) => this.config.cols.indexOf(a.col) - this.config.cols.indexOf(b.col))
- .attr('class', d => d.col)
- .each(function(d) {
- const cell = select(this);
-
- //Apply text in data as html or as plain text.
- if (table.config.as_html) {
- cell.html(d.text);
- } else {
- cell.text(d.text);
- }
- });
-}
diff --git a/src/table/draw/dynamicLayout.js b/src/table/draw/dynamicLayout.js
deleted file mode 100644
index d7433d6..0000000
--- a/src/table/draw/dynamicLayout.js
+++ /dev/null
@@ -1,44 +0,0 @@
-export default function dynamicLayout() {
- const widths = {
- table: this.table.select('thead').node().offsetWidth,
- top:
- this.wrap.select('.table-top .searchable-container').node().offsetWidth +
- this.wrap.select('.table-top .sortable-container').node().offsetWidth,
- bottom:
- this.wrap.select('.table-bottom .pagination-container').node().offsetWidth +
- this.wrap.select('.table-bottom .exportable-container').node().offsetWidth
- };
-
- if (widths.table < Math.max(widths.top, widths.bottom) && this.config.layout === 'horizontal') {
- this.config.layout = 'vertical';
- this.wrap
- .style('display', 'inline-block')
- .selectAll('.table-top,.table-bottom')
- .style('display', 'inline-block')
- .selectAll('.interactivity')
- .style({
- display: 'block',
- clear: 'both'
- });
- } else if (
- widths.table >= Math.max(widths.top, widths.bottom) &&
- this.config.layout === 'vertical'
- ) {
- this.config.layout = 'horizontal';
- this.wrap
- .style('display', 'table')
- .selectAll('.table-top,.table-bottom')
- .style('display', 'block')
- .selectAll('.interactivity')
- .style({
- display: 'inline-block',
- float: function() {
- return select(this).classed('searchable-container') ||
- select(this).classed('pagination-container')
- ? 'right'
- : null;
- },
- clear: null
- });
- }
-}
diff --git a/src/table/draw/updateDataObject.js b/src/table/draw/updateDataObject.js
deleted file mode 100644
index 26e9746..0000000
--- a/src/table/draw/updateDataObject.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function updateDataObject() {
- this.data.raw = this.data.passed;
- this.data.filtered = this.data.passed;
- this.config.activePage = 0;
- this.config.startIndex = this.config.activePage * this.config.nRowsPerPage; // first row shown
- this.config.endIndex = this.config.startIndex + this.config.nRowsPerPage; // last row shown
-}
diff --git a/src/table/draw/updateTableHeaders.js b/src/table/draw/updateTableHeaders.js
deleted file mode 100644
index 0806d4b..0000000
--- a/src/table/draw/updateTableHeaders.js
+++ /dev/null
@@ -1,9 +0,0 @@
-export default function updateTableHeaders() {
- this.thead_cells = this.thead.select('tr').selectAll('th').data(this.config.headers, d => d);
- this.thead_cells.exit().remove();
- this.thead_cells.enter().append('th');
- this.thead_cells
- .sort((a, b) => this.config.headers.indexOf(a) - this.config.headers.indexOf(b))
- .attr('class', d => this.config.cols[this.config.headers.indexOf(d)]) // associate column header with column name
- .text(d => d);
-}
diff --git a/src/table/exportable/exports/csv.js b/src/table/exportable/exports/csv.js
index f6fa48e..4e1ff51 100644
--- a/src/table/exportable/exports/csv.js
+++ b/src/table/exportable/exports/csv.js
@@ -3,12 +3,14 @@ import { time } from 'd3';
export default function csv(data) {
const CSVarray = [];
- //add headers to CSV array
- const headers = this.config.headers.map(header => `"${header.replace(/"/g, '""')}"`);
- CSVarray.push(headers);
-
- //add rows to CSV array
data.forEach((d, i) => {
+ //add headers to CSV array
+ if (i === 0) {
+ const headers = this.config.headers.map(header => `"${header.replace(/"/g, '""')}"`);
+ CSVarray.push(headers);
+ }
+
+ //add rows to CSV array
const row = this.config.cols.map(col => {
let value = d[col];
diff --git a/src/version.js b/src/version.js
index 2eef61b..80b72b7 100644
--- a/src/version.js
+++ b/src/version.js
@@ -1 +1 @@
-export default '1.11.0';
+export default '1.10.0';
diff --git a/test/chart/cleanData.js b/test/chart/cleanData.js
deleted file mode 100644
index ba0cd07..0000000
--- a/test/chart/cleanData.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import jsdom from 'jsdom';
-import createChart from '../../src/createChart';
-import cleanData from '../../src/chart/draw/consolidateData/transformData/cleanData';
-import expect from 'expect';
-import d3 from 'd3';
-
-export default function testCleanData(settings, data) {
- describe('data cleaning', () => {
- const { JSDOM } = jsdom;
- let dom, container, chart;
-
- //DOM setup
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
-
- //Chart initialization
- beforeEach(() => {
- chart = createChart(container, settings).init(data, true);
- });
-
- //transformData() validation
- describe('cleanData() is called for each item in settings.marks', () => {
- const falseyValues = [
- '',
- ' ',
- 'asdf',
- NaN,
- null,
- undefined,
- false
- ];
- settings.marks.forEach(mark => {
- let copiedData, cleanedData;
-
- beforeEach(() => {
- copiedData = [];
- data.forEach((d,i) => {
- copiedData[i] = {};
- for (const variable in d)
- copiedData[i][variable] = d[variable];
-
- if (Math.random() < .1)
- copiedData[i][settings.x.column] = falseyValues[i%(falseyValues.length - 1)];
- if (Math.random() > .9)
- copiedData[i][settings.y.column] = falseyValues[i%(falseyValues.length - 1)];
- });
-
- cleanedData = cleanData.call(chart, mark, copiedData);
- });
-
- it('removes falsey values', () => {
- const cleanedCopiedData = copiedData
- .filter(d => (
- falseyValues.indexOf(d[settings.x.column]) < 0 &&
- !isNaN(d[settings.x.column]) &&
- falseyValues.indexOf(d[settings.y.column]) < 0 &&
- !isNaN(d[settings.y.column])
- ));
- expect(
- cleanedData.length
- ).toEqual(
- cleanedCopiedData.length
- );
- });
- });
- });
- });
-}
diff --git a/test/chart/consolidateData.js b/test/chart/consolidateData.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/chart/draw.js b/test/chart/draw.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/chart/rangeBand.js b/test/chart/rangeBand.js
deleted file mode 100644
index b26f862..0000000
--- a/test/chart/rangeBand.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import jsdom from 'jsdom';
-import createChart from '../../src/createChart';
-import expect from 'expect';
-import d3 from 'd3';
-
-export default function testRangeBand(settings, data) {
- describe('range band definitions for ordinal axes', () => {
- const { JSDOM } = jsdom;
- let dom, container, chart;
-
- //DOM setup
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
-
- //Chart initialization
- beforeEach(() => {
- chart = createChart(container, settings).init(data, true);
- });
-
- afterEach(() => {
- delete chart.config.range_band;
- delete chart.config.x.range_band;
- delete chart.config.y.range_band;
- });
-
- describe('x-axis range band', () => {
- it('sets bar width to config.range_band if config.x.range_band is undefined', () => {
- chart.config.range_band = 25;
- chart.draw();
- expect(chart.config.range_band).toEqual(chart.x.rangeBand());
- });
-
- it('sets bar width to config.x.range_band otherwise', () => {
- chart.config.x.range_band = 20;
- chart.draw();
- expect(chart.config.x.range_band).toEqual(chart.x.rangeBand());
- });
- });
-
- describe('y-axis range band', () => {
- it('sets bar width to config.range_band if config.y.range_band is undefined', () => {
- chart.config.range_band = 25;
- chart.draw();
- expect(chart.config.range_band).toEqual(chart.y.rangeBand());
- });
-
- it('sets bar width to config.y.range_band otherwise', () => {
- chart.config.y.range_band = 30;
- chart.draw();
- expect(chart.config.y.range_band).toEqual(chart.y.rangeBand());
- });
- });
-
- describe('x- and y-axis range band', () => {
- it('sets bar width to config.range_band if both config.x.range_band and config.y.range_band are undefined', () => {
- chart.config.range_band = 25;
- chart.draw();
- expect(
- chart.config.range_band === chart.x.rangeBand() &&
- chart.config.range_band === chart.y.rangeBand()
- ).toEqual(true);
- });
-
- it('sets bar width independently for each axis otherwise', () => {
- chart.config.x.range_band = 20;
- chart.config.y.range_band = 30;
- chart.draw();
- expect(
- chart.config.x.range_band === chart.x.rangeBand() &&
- chart.config.y.range_band === chart.y.rangeBand()
- ).toEqual(true);
- });
- });
- });
-}
diff --git a/test/chart/runTests.js b/test/chart/runTests.js
index 8a887fc..2840746 100644
--- a/test/chart/runTests.js
+++ b/test/chart/runTests.js
@@ -1,61 +1,34 @@
-//define chart object
import testCreateChart from './createChart';
-import { linear_linear as createChartSettings } from '../samples/irisSettings';
+
+import createChartSettings from '../samples/irisSettings';
testCreateChart(createChartSettings);
-//initialize chart by passing a data array to the init method
import testInit from './init';
-import { linear_linear as initSettings } from '../samples/irisSettings';
+
+import initSettings from '../samples/irisSettings';
import initData from '../samples/irisData';
testInit(initSettings, initData);
-//render chart in DOM
import testRendering from './rendering';
+
import renderSettings from '../samples/element-settings';
import renderData from '../samples/data';
testRendering(renderSettings, renderData);
-//check for required variables in data array
import testCheckRequired from './checkRequired';
-import { linear_linear as checkRequiredSettings } from '../samples/irisSettings';
+
+import checkRequiredSettings from '../samples/irisSettings';
import checkRequiredData from '../samples/irisData';
testCheckRequired(checkRequiredSettings, checkRequiredData);
-//generate layout of chart
import testLayout from './layout';
-import { linear_linear as layoutSettings } from '../samples/irisSettings';
+
+import layoutSettings from '../samples/irisSettings';
import layoutData from '../samples/irisData';
testLayout(layoutSettings, layoutData);
-//define color scale of chart
import testSetColorScale from './setColorScale';
-import { linear_linear as setColorScaleSettings } from '../samples/irisSettings';
+
+import setColorScaleSettings from '../samples/irisSettings';
import setColorScaleData from '../samples/irisData';
testSetColorScale(setColorScaleSettings, setColorScaleData);
-
-//transform raw data for each mark defined in chart config
-import testTransformData from './transformData';
-import { linear_linear as transformDataSettings } from '../samples/irisSettings';
-import transformDataData from '../samples/irisData';
-testTransformData(transformDataSettings, transformDataData);
-
-//define singular domain for chart
-import testSetDomain from './setDomain';
-import { linear_linear, linear_ordinal, ordinal_linear } from '../samples/irisSettings';
-import setDomainData from '../samples/irisData';
-testSetDomain({linear_linear, linear_ordinal, ordinal_linear}, setDomainData);
-
-//remove falsey values from data
-import testCleanData from './cleanData';
-import { linear_linear as cleanDataSettings } from '../samples/irisSettings';
-import cleanDataData from '../samples/irisData';
-testCleanData(cleanDataSettings, cleanDataData);
-
-//test range band settings
-import testRangeBand from './rangeBand';
-import { ordinal_ordinal as ordinal_ordinal_rb } from '../samples/irisSettings';
-import rangeBandData from '../samples/irisData';
-testRangeBand(
- ordinal_ordinal_rb,
- rangeBandData
-);
diff --git a/test/chart/setDomain.js b/test/chart/setDomain.js
deleted file mode 100644
index 2726d92..0000000
--- a/test/chart/setDomain.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import jsdom from 'jsdom';
-import createChart from '../../src/createChart';
-import expect from 'expect';
-import d3 from 'd3';
-
-export default function testSetDomain(settings, data) {
- describe('chart domains', () => {
- const { JSDOM } = jsdom;
- let dom, container, charts;
-
- //DOM setup
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
-
- beforeEach(() => {
- charts = {
- linear_linear: createChart(container, settings.linear_linear).init(data, true),
- ordinal_linear: createChart(container, settings.ordinal_linear).init(data, true),
- linear_ordinal: createChart(container, settings.linear_ordinal).init(data, true)
- };
- });
-
- afterEach(() => {
- for (const chart in chart) {
- delete charts[chart].config.x.domain;
- delete charts[chart].x_dom;
- delete charts[chart].config.y.domain;
- delete charts[chart].y_dom;
- }
- });
-
- //linear x linear
- describe('setDomain() is called for a chart with two linear axes', () => {
- ['x','y'].forEach(axis => {
- it('returns a non-zero-length array for the specified axis', () => {
- console.log(` - testing ${charts.linear_linear[axis].type} ${axis} axis:`);
- expect(charts.linear_linear[axis + '_dom'].length).toBeGreaterThan(0);
- });
-
- it('does not return a zero-range domain for the specified axis', () => {
- const test_data = [];
- data.forEach(d => {
- const datum = {};
- for (const prop in d)
- datum[prop] = d[prop];
- datum[charts.linear_linear[axis].column] = 0;
- test_data.push(datum);
- });
- charts.linear_linear.consolidateData(test_data);
- expect(charts.linear_linear[axis + '_dom'][1] - charts.linear_linear[axis + '_dom'][0]).toBeGreaterThan(0);
- });
-
- it('gives precedence to the domain defined in the config', () => {
- const domain = [-100,100];
- charts.linear_linear.config[axis].domain = domain.slice();
- charts.linear_linear.consolidateData(data);
- expect(charts.linear_linear[axis + '_dom'].join(',')).toEqual(domain.join(','));
- });
- });
- });
-
- //ordinal x linear
- describe('setDomain() is called for a chart with an ordinal x-axis and a linear y-axis', () => {
- it('returns a unique set of the ordinal axis variable as its domain', () => {
- const ordinalDomain = d3
- .set(data.map(d => d[charts.ordinal_linear.config.x.column]))
- .values()
- .sort()
- .join(', ');
- expect(charts.ordinal_linear.x_dom.sort().join(', ')).toEqual(ordinalDomain);
- });
-
- it('sets the lower limit of the linear domain to 0', () => {
- expect(charts.ordinal_linear.y_dom[0]).toEqual(0);
- });
-
- it('sets the upper limit of the linear domain to the maximum value of the linear axis variable', () => {
- const upperLimit = d3.max(data.map(d => d[charts.ordinal_linear.config.y.column]));
- expect(charts.ordinal_linear.y_dom[1]).toEqual(upperLimit);
- });
- });
-
- //linear x ordinal
- describe('setDomain() is called for a chart with an linear x-axis and a ordinal y-axis', () => {
- it('sets the lower limit of the linear domain to 0', () => {
- expect(charts.linear_ordinal.x_dom[0]).toEqual(0);
- });
-
- it('sets the upper limit of the linear domain to the maximum value of the linear axis variable', () => {
- const upperLimit = d3.max(data.map(d => d[charts.linear_ordinal.config.x.column]));
- expect(charts.linear_ordinal.x_dom[1]).toEqual(upperLimit);
- });
-
- it('returns a unique set of the ordinal axis variable as its domain', () => {
- const ordinalDomain = d3
- .set(data.map(d => d[charts.linear_ordinal.config.y.column]))
- .values()
- .sort()
- .join(', ');
- expect(charts.linear_ordinal.y_dom.sort().join(', ')).toEqual(ordinalDomain);
- });
- });
- });
-}
diff --git a/test/chart/transformData.js b/test/chart/transformData.js
index 198b7fe..a10c668 100644
--- a/test/chart/transformData.js
+++ b/test/chart/transformData.js
@@ -1,94 +1,95 @@
import jsdom from 'jsdom';
import createChart from '../../src/createChart';
+import transformData from '../../src/chart/transformData';
import expect from 'expect';
+import settings from '../samples/irisSettings';
+import data from '../samples/irisData';
import d3 from 'd3';
-export default function testTransformData(settings, data) {
- describe('data transformation', () => {
- const { JSDOM } = jsdom;
- let dom, container, chart;
+describe('data transformation', () => {
+ const { JSDOM } = jsdom;
+ let dom, container, chart;
- //DOM setup
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
+ //DOM setup
+ before(() => {
+ dom = new JSDOM('');
+ container = dom.window.document.createElement('div');
+ });
- //Chart initialization
- beforeEach(() => {
- chart = createChart(container, settings).init(data, true);
- });
+ //Chart initialization
+ beforeEach(() => {
+ chart = createChart(container, settings).init(data, true);
+ });
- //transformData() validation
- describe('transformData() is called for each item in settings.marks', () => {
- settings.marks.forEach(mark => {
- let transformedData, nestedData;
+ //transformData() validation
+ describe('transformData() is called for each item in settings.marks', () => {
+ settings.marks.forEach(mark => {
+ let transformedData, nestedData;
- beforeEach(() => {
- transformedData = chart.transformData(data, mark); // webcharts dataset
- nestedData = d3
- .nest() // validation dataset
- .key(d => mark.per.map(per => d[per]).join(' '))
- .rollup(d => {
- return {
- raw: d,
- x: d3[mark.summarizeX](d, di => di[settings.x.column]),
- y: d3[mark.summarizeY](d, di => di[settings.y.column]),
- x_q25: d3.quantile(d.map(di => di[settings.x.column]), 0.25),
- x_q75: d3.quantile(d.map(di => di[settings.x.column]), 0.75),
- y_q25: d3.quantile(d.map(di => di[settings.y.column]), 0.25),
- y_q75: d3.quantile(d.map(di => di[settings.y.column]), 0.75)
- };
- })
- .entries(data);
- });
+ beforeEach(() => {
+ transformedData = chart.transformData(data, mark); // webcharts dataset
+ nestedData = d3
+ .nest() // validation dataset
+ .key(d => mark.per.map(per => d[per]).join(' '))
+ .rollup(d => {
+ return {
+ raw: d,
+ x: d3[mark.summarizeX](d, di => di[settings.x.column]),
+ y: d3[mark.summarizeY](d, di => di[settings.y.column]),
+ x_q25: d3.quantile(d.map(di => di[settings.x.column]), 0.25),
+ x_q75: d3.quantile(d.map(di => di[settings.x.column]), 0.75),
+ y_q25: d3.quantile(d.map(di => di[settings.y.column]), 0.25),
+ y_q75: d3.quantile(d.map(di => di[settings.y.column]), 0.75)
+ };
+ })
+ .entries(data);
+ });
- it('returns an object containing a config, a nested data array, an x-domain, and a y-domain', () => {
- console.log(`\n Testing ${mark.summarizeX}:\n`);
- expect(Object.keys(transformedData)).toEqual(['config','data', 'x_dom', 'y_dom']);
- });
+ it('returns an object containing a config, a nested data array, an x-domain, and a y-domain', () => {
+ console.log(`\n Testing ${mark.summarizeX}:\n`);
+ expect(Object.keys(transformedData)).toEqual(['config','data', 'x_dom', 'y_dom']);
+ });
- it('nests raw data by mark.per', () => {
- expect(nestedData.length).toEqual(transformedData.data.length);
- expect(nestedData.map(d => d.key)).toEqual(transformedData.data.map(d => d.key));
+ it('nests raw data by mark.per', () => {
+ expect(nestedData.length).toEqual(transformedData.data.length);
+ expect(nestedData.map(d => d.key)).toEqual(transformedData.data.map(d => d.key));
- nestedData.forEach(d => {
- const transformedDatum = transformedData.data.filter(di => di.key === d.key)[0];
+ nestedData.forEach(d => {
+ const transformedDatum = transformedData.data.filter(di => di.key === d.key)[0];
- expect(d.values.raw).toEqual(transformedDatum.values.raw);
- expect(d.values.x).toEqual(transformedDatum.values.x);
- expect(d.values.y).toEqual(transformedDatum.values.y);
- expect(d.values.x_25).toEqual(transformedDatum.values.x_25);
- expect(d.values.x_75).toEqual(transformedDatum.values.x_75);
- expect(d.values.y_25).toEqual(transformedDatum.values.y_25);
- expect(d.values.y_75).toEqual(transformedDatum.values.y_75);
- });
+ expect(d.values.raw).toEqual(transformedDatum.values.raw);
+ expect(d.values.x).toEqual(transformedDatum.values.x);
+ expect(d.values.y).toEqual(transformedDatum.values.y);
+ expect(d.values.x_25).toEqual(transformedDatum.values.x_25);
+ expect(d.values.x_75).toEqual(transformedDatum.values.x_75);
+ expect(d.values.y_25).toEqual(transformedDatum.values.y_25);
+ expect(d.values.y_75).toEqual(transformedDatum.values.y_75);
});
+ });
- it('sets x-domain to extent of values in x-column', () => {
- expect(Math.min.apply(null, nestedData.map(d => d.values.x))).toEqual(
- transformedData.x_dom[0]
- );
- expect(Math.max.apply(null, nestedData.map(d => d.values.x))).toEqual(
- transformedData.x_dom[1]
- );
- });
+ it('sets x-domain to extent of values in x-column', () => {
+ expect(Math.min.apply(null, nestedData.map(d => d.values.x))).toEqual(
+ transformedData.x_dom[0]
+ );
+ expect(Math.max.apply(null, nestedData.map(d => d.values.x))).toEqual(
+ transformedData.x_dom[1]
+ );
+ });
- it('sets y-domain to extent of values in y-column', () => {
- expect(Math.min.apply(null, nestedData.map(d => d.values.y))).toEqual(
- transformedData.y_dom[0]
- );
- expect(Math.max.apply(null, nestedData.map(d => d.values.y))).toEqual(
- transformedData.y_dom[1]
- );
- });
+ it('sets y-domain to extent of values in y-column', () => {
+ expect(Math.min.apply(null, nestedData.map(d => d.values.y))).toEqual(
+ transformedData.y_dom[0]
+ );
+ expect(Math.max.apply(null, nestedData.map(d => d.values.y))).toEqual(
+ transformedData.y_dom[1]
+ );
});
});
+ });
- describe('chart object has marks property', () => {
- it('marks property has the same length as settings.marks', () => {
- expect(settings.marks.length).toEqual(chart.marks.length);
- });
+ describe('chart object has marks property', () => {
+ it('marks property has the same length as settings.marks', () => {
+ expect(settings.marks.length).toEqual(chart.marks.length);
});
});
-}
+});
diff --git a/test/multiply/multiply.js b/test/multiply/multiply.js
index 7b4514b..1542c54 100644
--- a/test/multiply/multiply.js
+++ b/test/multiply/multiply.js
@@ -3,11 +3,10 @@ import createChart from '../../src/createChart';
import multiply from '../../src/multiply';
import expect from 'expect';
import irisData from '../samples/irisData';
-import { linear_linear as irisSettings } from '../samples/irisSettings';
-import clone from '../../src/util/clone';
-import { selectAll } from 'd3';
+import irisSettings from '../samples/irisSettings';
+import chartProto from '../../src/chart/index';
-describe('chart.multiply()', () => {
+describe('chart multiply', () => {
const { JSDOM } = jsdom;
let dom, container, chart;
@@ -30,24 +29,5 @@ describe('chart.multiply()', () => {
it('multiple object should link back to master chart', () => {
expect(chart.multiples[0].parent).toEqual(chart);
});
-
- it('a single legend should exist inside the parent node of the multiples', () => {
- expect(chart.wrap.selectAll('.legend').size()).toEqual(1);
- });
-
- it('appears after multiples by default', () => {
- const nodes = chart.wrap.node().querySelectorAll('div,ul');
- expect(nodes[nodes.length - 1]).toEqual(chart.master_legend.node());
- });
-
- it('appears before multiples if legend location is set to top', () => {
- const topLegendSettings = clone(irisSettings);
- topLegendSettings.legend.location = 'top';
- chart = createChart(container, topLegendSettings);
- multiply(chart, irisData, 'Species', null, true);
-
- const nodes = chart.wrap.node().querySelectorAll('div,ul');
- expect(nodes[0]).toEqual(chart.master_legend.node());
- });
});
});
diff --git a/test/samples/irisSettings.js b/test/samples/irisSettings.js
index 95b05e0..8768b6e 100644
--- a/test/samples/irisSettings.js
+++ b/test/samples/irisSettings.js
@@ -1,4 +1,4 @@
-export const linear_linear = {
+export default {
x: {
type: 'linear',
column: 'Sepal.Length',
@@ -15,6 +15,9 @@ export const linear_linear = {
per: ['Sepal.Length', 'Sepal.Width'],
summarizeX: 'mean',
summarizeY: 'mean',
+ values: {
+ Species: ['setosa', 'versicolor', 'virginica']
+ }
},
{
type: 'circle',
@@ -38,113 +41,3 @@ export const linear_linear = {
color_by: 'Species',
legend: {}
};
-
-export const ordinal_linear = {
- x: {
- type: 'ordinal',
- column: 'Species',
- label: 'Species'
- },
- y: {
- type: 'linear',
- column: 'Sepal.Length',
- label: 'Sepal Length'
- },
- marks: [
- {
- type: 'bar',
- per: ['Species'],
- summarizeY: 'mean',
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeY: 'min'
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeY: 'median'
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeY: 'max'
- },
- ],
- color_by: 'Species',
- legend: {},
- padding: 0,
- outer_pad: 0,
-};
-
-export const linear_ordinal = {
- x: {
- type: 'linear',
- column: 'Sepal.Length',
- label: 'Sepal Length'
- },
- y: {
- type: 'ordinal',
- column: 'Species',
- label: 'Species'
- },
- marks: [
- {
- type: 'bar',
- per: ['Species'],
- summarizeX: 'mean',
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeX: 'min'
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeX: 'median'
- },
- {
- type: 'circle',
- per: ['Species'],
- summarizeX: 'max'
- },
- ],
- color_by: 'Species',
- legend: {},
- padding: 0,
- outer_pad: 0,
-};
-
-export const ordinal_ordinal = {
- x: {
- type: 'ordinal',
- column: 'Species',
- label: 'Species'
- },
- y: {
- type: 'ordinal',
- column: 'Species',
- label: 'Species'
- },
- marks: [
- {
- type: 'bar',
- per: ['Species'],
- },
- {
- type: 'circle',
- per: ['Species'],
- },
- {
- type: 'text',
- per: ['Species'],
- text: '$x - $y',
- },
- ],
- color_by: 'Species',
- legend: {},
- padding: 0,
- outer_pad: 0,
-};
diff --git a/test/table/bindTableToDOM.js b/test/table/bindTableToDOM.js
deleted file mode 100644
index 0b09339..0000000
--- a/test/table/bindTableToDOM.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import jsdom from 'jsdom';
-import createTable from '../../src/createTable';
-import expect from 'expect';
-
-export default function bindTableToDOM(settings, data) {
- describe('table object in DOM', () => {
- const { JSDOM } = jsdom;
- let dom, container, table;
-
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
-
- beforeEach(() => {
- table = createTable(container, settings).init(data, true);
- });
-
- afterEach(() => {
- });
-
- describe('user calls table init() method', () => {
- it('binds table object to parent of table node', () => {
- expect(table.wrap.datum()).toEqual(table);
- });
-
- it('binds table data to table node', () => {
- expect(table.table.datum()).toEqual(table.data.current);
- });
- });
- });
-}
diff --git a/test/table/init.js b/test/table/init.js
deleted file mode 100644
index 8322c47..0000000
--- a/test/table/init.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import jsdom from 'jsdom';
-import createTable from '../../src/createTable';
-import expect from 'expect';
-
-export default function testInit(settings, data) {
- describe('table initialization and lifecycle', () => {
- const { JSDOM } = jsdom;
- let dom, container, table;
-
- before(() => {
- dom = new JSDOM('');
- container = dom.window.document.createElement('div');
- });
-
- beforeEach(() => {
- table = createTable(container, settings);
-
- expect.spyOn(table.events, 'onInit');
- expect.spyOn(table.events, 'onLayout');
- expect.spyOn(table.events, 'onPreprocess');
- expect.spyOn(table.events, 'onDraw');
-
- table.init(data, true);
- });
-
- afterEach(() => {
- container.children[0].remove();
- table = null;
- });
-
- describe('user calls table init() method', () => {
- it('webCharts attaches raw data', () => {
- expect(table.data.raw).toEqual(data);
- });
- });
-
- describe('should run all .on([lifecycle]) functions when initialized with marks specified in the config', () => {
- it('should call onInit', () => {
- expect(table.events.onInit).toHaveBeenCalled();
- });
- it('should call onLayout', () => {
- expect(table.events.onLayout).toHaveBeenCalled();
- });
- it('should call onPreprocess', () => {
- expect(table.events.onPreprocess).toHaveBeenCalled();
- });
- it('should call onDraw', () => {
- expect(table.events.onDraw).toHaveBeenCalled();
- });
- });
-
- describe('should run repeated .on([lifecycle]) functions when .draw() is called independently', () => {
- beforeEach(() => {
- table.draw();
- });
- it('onPreprocess has been called twice', () => {
- expect(table.events.onPreprocess).toHaveBeenCalled();
- expect(table.events.onPreprocess.calls.length).toEqual(2);
- });
- it('onDraw has been called twice', () => {
- expect(table.events.onDraw).toHaveBeenCalled();
- expect(table.events.onDraw.calls.length).toEqual(2);
- });
- });
- });
-}
diff --git a/test/table/runTests.js b/test/table/runTests.js
index a0816c3..f6075f2 100644
--- a/test/table/runTests.js
+++ b/test/table/runTests.js
@@ -1,25 +1,16 @@
import data from '../samples/irisData';
-import testInit from './init';
-testInit(
+import testDestroyTable from './destroyTable';
+testDestroyTable(
{ exportable: false },
- data
-);
+ data);
import testSearchTable from './searchTable';
testSearchTable(
{ sortable: false, searchable: true, exportable: false, pagination: false },
- data
-);
+ data);
import testSortTable from './sortTable';
testSortTable(
{ sortable: true, searchable: false, exportable: false, pagination: false },
- data
-);
-
-import testDestroyTable from './destroyTable';
-testDestroyTable(
- { exportable: false },
- data
-);
+ data);
diff --git a/test/testNewUnitTests.js b/test/testNewUnitTests.js
deleted file mode 100644
index 480fe08..0000000
--- a/test/testNewUnitTests.js
+++ /dev/null
@@ -1 +0,0 @@
-import './multiply/multiply';