vendor/assets/javascripts/nvd3.js in chart-0.1.4.8 vs vendor/assets/javascripts/nvd3.js in chart-0.1.4.9
- old
+ new
@@ -1,6 +1,6 @@
-/* nvd3 version 1.8.3 (https://github.com/novus/nvd3) 2016-04-26 */
+/* nvd3 version 1.8.4 (https://github.com/novus/nvd3) 2016-07-03 */
(function(){
// set up main nv object
var nv = {};
@@ -152,35 +152,35 @@
}
if (typeof(window) !== 'undefined') {
window.nv = nv;
}
-/* Facade for queueing DOM write operations
- * with Fastdom (https://github.com/wilsonpage/fastdom)
- * if available.
- * This could easily be extended to support alternate
- * implementations in the future.
- */
-nv.dom.write = function(callback) {
- if (window.fastdom !== undefined) {
- return fastdom.mutate(callback);
- }
- return callback();
-};
-
-/* Facade for queueing DOM read operations
- * with Fastdom (https://github.com/wilsonpage/fastdom)
- * if available.
- * This could easily be extended to support alternate
- * implementations in the future.
- */
-nv.dom.read = function(callback) {
- if (window.fastdom !== undefined) {
- return fastdom.measure(callback);
- }
- return callback();
-};
+/* Facade for queueing DOM write operations
+ * with Fastdom (https://github.com/wilsonpage/fastdom)
+ * if available.
+ * This could easily be extended to support alternate
+ * implementations in the future.
+ */
+nv.dom.write = function(callback) {
+ if (window.fastdom !== undefined) {
+ return fastdom.mutate(callback);
+ }
+ return callback();
+};
+
+/* Facade for queueing DOM read operations
+ * with Fastdom (https://github.com/wilsonpage/fastdom)
+ * if available.
+ * This could easily be extended to support alternate
+ * implementations in the future.
+ */
+nv.dom.read = function(callback) {
+ if (window.fastdom !== undefined) {
+ return fastdom.measure(callback);
+ }
+ return callback();
+};
/* Utility class to handle creation of an interactive layer.
This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch
containing the X-coordinate. It can also render a vertical line where the mouse is located.
dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over
@@ -196,11 +196,11 @@
, xScale = d3.scale.linear()
, dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick', 'elementMouseDown', 'elementMouseUp')
, showGuideLine = true
, svgContainer = null // Must pass the chart's svg, we'll use its mousemove event.
, tooltip = nv.models.tooltip()
- , isMSIE = "ActiveXObject" in window // Checkt if IE by looking for activeX.
+ , isMSIE = window.ActiveXObject// Checkt if IE by looking for activeX. (excludes IE11)
;
tooltip
.duration(0)
.hideDelay(0)
@@ -543,35 +543,20 @@
, data = null
, gravity = 'w' // Can be 'n','s','e','w'. Determines how tooltip is positioned.
, distance = 25 // Distance to offset tooltip from the mouse location.
, snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
, classes = null // Attaches additional CSS classes to the tooltip DIV that is created.
- , chartContainer = null // Parent dom element of the SVG that holds the chart.
, hidden = true // Start off hidden, toggle with hide/show functions below.
, hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide().
, tooltip = null // d3 select of the tooltip div.
, lastPosition = { left: null, top: null } // Last position the tooltip was in.
, enabled = true // True -> tooltips are rendered. False -> don't render tooltips.
, duration = 100 // Tooltip movement duration, in ms.
, headerEnabled = true // If is to show the tooltip header.
, nvPointerEventsClass = "nv-pointer-events-none" // CSS class to specify whether element should not have mouse events.
;
- /*
- Function that returns the position (relative to the viewport) the tooltip should be placed in.
- Should return: {
- left: <leftPos>,
- top: <topPos>
- }
- */
- var position = function() {
- return {
- left: d3.event !== null ? d3.event.clientX : 0,
- top: d3.event !== null ? d3.event.clientY : 0
- };
- };
-
// Format function for the tooltip values column.
var valueFormatter = function(d, i) {
return d;
};
@@ -627,10 +612,14 @@
trowEnter.append("td")
.classed("value",true)
.html(function(p, i) { return valueFormatter(p.value, i) });
+ trowEnter.filter(function (p,i) { return p.percent !== undefined }).append("td")
+ .classed("percent", true)
+ .html(function(p, i) { return "(" + d3.format('%')(p.percent) + ")" });
+
trowEnter.selectAll("td").each(function(p) {
if (p.highlight) {
var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]);
var opacity = 0.6;
d3.select(this)
@@ -645,10 +634,35 @@
html += "<div class='footer'>" + d.footer + "</div>";
return html;
};
+ /*
+ Function that returns the position (relative to the viewport/document.body)
+ the tooltip should be placed in.
+ Should return: {
+ left: <leftPos>,
+ top: <topPos>
+ }
+ */
+ var position = function() {
+ var pos = {
+ left: d3.event !== null ? d3.event.clientX : 0,
+ top: d3.event !== null ? d3.event.clientY : 0
+ };
+
+ if(getComputedStyle(document.body).transform != 'none') {
+ // Take the offset into account, as now the tooltip is relative
+ // to document.body.
+ var client = document.body.getBoundingClientRect();
+ pos.left -= client.left;
+ pos.top -= client.top;
+ }
+
+ return pos;
+ };
+
var dataSeriesExists = function(d) {
if (d && d.series) {
if (nv.utils.isArray(d.series)) {
return true;
}
@@ -732,11 +746,11 @@
.duration(0)
.style('opacity', 0);
} else {
// using tooltip.style('transform') returns values un-usable for tween
var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)';
- var new_translate = 'translate(' + left + 'px, ' + top + 'px)';
+ var new_translate = 'translate(' + Math.round(left) + 'px, ' + Math.round(top) + 'px)';
var translateInterpolator = d3.interpolateString(old_translate, new_translate);
var is_hidden = tooltip.style('opacity') < 0.1;
tooltip
.interrupt() // cancel running transitions
@@ -760,15 +774,14 @@
};
// Creates new tooltip container, or uses existing one on DOM.
function initTooltip() {
if (!tooltip || !tooltip.node()) {
- var container = chartContainer ? chartContainer : document.body;
// Create new tooltip div if it doesn't exist on DOM.
var data = [1];
- tooltip = d3.select(container).selectAll('.nvtooltip').data(data);
+ tooltip = d3.select(document.body).selectAll('.nvtooltip').data(data);
tooltip.enter().append('div')
.attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip"))
.attr("id", id)
.style("top", 0).style("left", 0)
@@ -810,21 +823,24 @@
duration: {get: function(){return duration;}, set: function(_){duration=_;}},
gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}},
distance: {get: function(){return distance;}, set: function(_){distance=_;}},
snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}},
classes: {get: function(){return classes;}, set: function(_){classes=_;}},
- chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}},
enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}},
hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}},
contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}},
valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}},
headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}},
keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}},
position: {get: function(){return position;}, set: function(_){position=_;}},
// Deprecated options
+ chartContainer: {get: function(){return document.body;}, set: function(_){
+ // deprecated after 1.8.3
+ nv.deprecated('chartContainer', 'feature removed after 1.8.3');
+ }},
fixedTop: {get: function(){return null;}, set: function(_){
// deprecated after 1.8.1
nv.deprecated('fixedTop', 'feature removed after 1.8.1');
}},
offset: {get: function(){return {left: 0, top: 0};}, set: function(_){
@@ -1548,11 +1564,11 @@
return true;
if (!array1 || !array2)
return false;
- // compare lengths - can save a lot of time
+ // compare lengths - can save a lot of time
if (array1.length != array2.length)
return false;
for (var i = 0,
l = array1.length; i < l; i++) {
@@ -1565,11 +1581,12 @@
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
-};nv.models.axis = function() {
+};
+nv.models.axis = function() {
"use strict";
//============================================================
// Public Variables with Default Settings
//------------------------------------------------------------
@@ -1690,11 +1707,11 @@
var textHeight = 0;
var xTicks = g.selectAll('g').select("text");
var rotateLabelsRule = '';
if (rotateLabels%360) {
//Reset transform on ticks so textHeight can be calculated correctly
- xTicks.attr('transform', '');
+ xTicks.attr('transform', '');
//Calculate the longest xTick width
xTicks.each(function(d,i){
var box = this.getBoundingClientRect();
var width = box.width;
textHeight = box.height;
@@ -1763,11 +1780,11 @@
case 'right':
axisLabel.enter().append('text').attr('class', 'nv-axislabel');
axisLabel
.style('text-anchor', rotateYLabel ? 'middle' : 'begin')
.attr('transform', rotateYLabel ? 'rotate(90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
+ .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12 - (axisLabelDistance || 0)) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
.attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding());
if (showMaxMin) {
axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
.data(scale.domain());
axisMaxMin.enter().append('g').attr('class',function(d,i){
@@ -1898,13 +1915,13 @@
The filter needs to return only ticks at or near zero.
Numbers like 0.00001 need to count as zero as well,
and the arithmetic trick below solves that.
*/
return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined)
- })
+ })
.classed('zero', true);
-
+
//store old scales for use in transitions on update
scale0 = scale.copy();
});
@@ -2531,13 +2548,15 @@
var margin = {top: 0, right: 0, bottom: 0, left: 0}
, orient = 'left' // TODO top & bottom
, reverse = false
, ranges = function(d) { return d.ranges }
, markers = function(d) { return d.markers ? d.markers : [] }
+ , markerLines = function(d) { return d.markerLines ? d.markerLines : [0] }
, measures = function(d) { return d.measures }
, rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }
, markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }
+ , markerLineLabels = function(d) { return d.markerLineLabels ? d.markerLineLabels : [] }
, measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }
, forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
, width = 380
, height = 30
, container = null
@@ -2565,18 +2584,21 @@
container = d3.select(this);
nv.utils.initSVG(container);
var rangez = ranges.call(this, d, i).slice(),
markerz = markers.call(this, d, i).slice(),
+ markerLinez = markerLines.call(this, d, i).slice().sort(d3.descending),
measurez = measures.call(this, d, i).slice(),
rangeLabelz = rangeLabels.call(this, d, i).slice(),
markerLabelz = markerLabels.call(this, d, i).slice(),
+ markerLineLabelz = markerLineLabels.call(this, d, i).slice(),
measureLabelz = measureLabels.call(this, d, i).slice();
// Sort labels according to their sorted values
sortLabels(rangeLabelz, rangez);
sortLabels(markerLabelz, markerz);
+ sortLabels(markerLineLabelz, markerLinez);
sortLabels(measureLabelz, measurez);
// sort values descending
rangez.sort(d3.descending);
markerz.sort(d3.descending);
@@ -2700,10 +2722,52 @@
g.selectAll("path.nv-markerTriangle")
.data(markerData)
.attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' });
+ var markerLinesData = markerLinez.map( function(marker, index) {
+ return {value: marker, label: markerLineLabelz[index]}
+ });
+ gEnter
+ .selectAll("path.nv-markerLine")
+ .data(markerLinesData)
+ .enter()
+ .append('line')
+ .attr('cursor', '')
+ .attr('class', 'nv-markerLine')
+ .attr('x1', function(d) { return x1(d.value) })
+ .attr('y1', '2')
+ .attr('x2', function(d) { return x1(d.value) })
+ .attr('y2', availableHeight - 2)
+ .on('mouseover', function(d) {
+ dispatch.elementMouseover({
+ value: d.value,
+ label: d.label || 'Previous',
+ color: d3.select(this).style("fill"),
+ pos: [x1(d.value), availableHeight/2]
+ })
+
+ })
+ .on('mousemove', function(d) {
+ dispatch.elementMousemove({
+ value: d.value,
+ label: d.label || 'Previous',
+ color: d3.select(this).style("fill")
+ })
+ })
+ .on('mouseout', function(d, i) {
+ dispatch.elementMouseout({
+ value: d.value,
+ label: d.label || 'Previous',
+ color: d3.select(this).style("fill")
+ })
+ });
+
+ g.selectAll("path.nv-markerLines")
+ .data(markerLinesData)
+ .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' });
+
wrap.selectAll('.nv-range')
.on('mouseover', function(d,i) {
var label = rangeLabelz[i] || defaultRangeLabels[i];
dispatch.elementMouseover({
value: d,
@@ -3427,11 +3491,11 @@
g.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
g.select('.nv-legendWrap')
@@ -3682,11 +3746,10 @@
allData[indexToHighlight].highlight = true;
}
var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);
interactiveLayer.tooltip
- .chartContainer(that.parentNode)
.valueFormatter(function(d,i) {
return yAxis.tickFormat()(d);
})
.data(
{
@@ -4226,23 +4289,23 @@
g.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
wrap.select('.nv-legendWrap')
.attr('transform', 'translate(0,' + (-margin.top) +')')
}
-
+
if (rightAlignYAxis) {
g.select(".nv-y.nv-axis")
.attr("transform", "translate(" + availableWidth + ",0)");
- }
+ }
// Main Chart Component(s)
discretebar
.width(availableWidth)
.height(availableHeight);
@@ -4549,10 +4612,303 @@
//============================================================
return chart;
}
+nv.models.focus = function(content) {
+ "use strict";
+
+ //============================================================
+ // Public Variables with Default Settings
+ //------------------------------------------------------------
+
+ var content = content || nv.models.line()
+ , xAxis = nv.models.axis()
+ , yAxis = nv.models.axis()
+ , brush = d3.svg.brush()
+ ;
+
+ var margin = {top: 10, right: 0, bottom: 30, left: 0}
+ , color = nv.utils.defaultColor()
+ , width = null
+ , height = 70
+ , showXAxis = true
+ , showYAxis = false
+ , rightAlignYAxis = false
+ , ticks = null
+ , x
+ , y
+ , brushExtent = null
+ , duration = 250
+ , dispatch = d3.dispatch('brush', 'onBrush', 'renderEnd')
+ ;
+
+ content.interactive(false);
+ content.pointActive(function(d) { return false; });
+
+ //============================================================
+ // Private Variables
+ //------------------------------------------------------------
+
+ var renderWatch = nv.utils.renderWatch(dispatch, duration);
+
+ function chart(selection) {
+ renderWatch.reset();
+ renderWatch.models(content);
+ if (showXAxis) renderWatch.models(xAxis);
+ if (showYAxis) renderWatch.models(yAxis);
+
+ selection.each(function(data) {
+ var container = d3.select(this);
+ nv.utils.initSVG(container);
+ var availableWidth = nv.utils.availableWidth(width, container, margin),
+ availableHeight = height - margin.top - margin.bottom;
+
+ chart.update = function() {
+ if( duration === 0 ) {
+ container.call( chart );
+ } else {
+ container.transition().duration(duration).call(chart);
+ }
+ };
+ chart.container = this;
+
+ // Setup Scales
+ x = content.xScale();
+ y = content.yScale();
+
+ // Setup containers and skeleton of chart
+ var wrap = container.selectAll('g.nv-focus').data([data]);
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-focus').append('g');
+ var g = wrap.select('g');
+
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+
+ gEnter.append('g').attr('class', 'nv-background').append('rect');
+ gEnter.append('g').attr('class', 'nv-x nv-axis');
+ gEnter.append('g').attr('class', 'nv-y nv-axis');
+ gEnter.append('g').attr('class', 'nv-contentWrap');
+ gEnter.append('g').attr('class', 'nv-brushBackground');
+ gEnter.append('g').attr('class', 'nv-x nv-brush');
+
+ if (rightAlignYAxis) {
+ g.select(".nv-y.nv-axis")
+ .attr("transform", "translate(" + availableWidth + ",0)");
+ }
+
+ g.select('.nv-background rect')
+ .attr('width', availableWidth)
+ .attr('height', availableHeight);
+
+ content
+ .width(availableWidth)
+ .height(availableHeight)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled; }));
+
+ var contentWrap = g.select('.nv-contentWrap')
+ .datum(data.filter(function(d) { return !d.disabled; }));
+
+ d3.transition(contentWrap).call(content);
+
+ // Setup Brush
+ brush
+ .x(x)
+ .on('brush', function() {
+ onBrush();
+ });
+
+ if (brushExtent) brush.extent(brushExtent);
+
+ var brushBG = g.select('.nv-brushBackground').selectAll('g')
+ .data([brushExtent || brush.extent()]);
+
+ var brushBGenter = brushBG.enter()
+ .append('g');
+
+ brushBGenter.append('rect')
+ .attr('class', 'left')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight);
+
+ brushBGenter.append('rect')
+ .attr('class', 'right')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight);
+
+ var gBrush = g.select('.nv-x.nv-brush')
+ .call(brush);
+ gBrush.selectAll('rect')
+ .attr('height', availableHeight);
+ gBrush.selectAll('.resize').append('path').attr('d', resizePath);
+
+ onBrush();
+
+ g.select('.nv-background rect')
+ .attr('width', availableWidth)
+ .attr('height', availableHeight);
+
+ if (showXAxis) {
+ xAxis.scale(x)
+ ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
+ .tickSize(-availableHeight, 0);
+
+ g.select('.nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y.range()[0] + ')');
+ d3.transition(g.select('.nv-x.nv-axis'))
+ .call(xAxis);
+ }
+
+ if (showYAxis) {
+ yAxis
+ .scale(y)
+ ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
+ .tickSize( -availableWidth, 0);
+
+ d3.transition(g.select('.nv-y.nv-axis'))
+ .call(yAxis);
+ }
+
+ g.select('.nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y.range()[0] + ')');
+
+ //============================================================
+ // Event Handling/Dispatching (in chart's scope)
+ //------------------------------------------------------------
+
+ //============================================================
+ // Functions
+ //------------------------------------------------------------
+
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = availableHeight / 3;
+ return 'M' + (0.5 * x) + ',' + y
+ + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
+ + 'V' + (2 * y - 6)
+ + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y)
+ + 'Z'
+ + 'M' + (2.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8)
+ + 'M' + (4.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8);
+ }
+
+
+ function updateBrushBG() {
+ if (!brush.empty()) brush.extent(brushExtent);
+ brushBG
+ .data([brush.empty() ? x.domain() : brushExtent])
+ .each(function(d,i) {
+ var leftWidth = x(d[0]) - x.range()[0],
+ rightWidth = availableWidth - x(d[1]);
+ d3.select(this).select('.left')
+ .attr('width', leftWidth < 0 ? 0 : leftWidth);
+
+ d3.select(this).select('.right')
+ .attr('x', x(d[1]))
+ .attr('width', rightWidth < 0 ? 0 : rightWidth);
+ });
+ }
+
+
+ function onBrush() {
+ brushExtent = brush.empty() ? null : brush.extent();
+ var extent = brush.empty() ? x.domain() : brush.extent();
+
+ //The brush extent cannot be less than one. If it is, don't update the line chart.
+ if (Math.abs(extent[0] - extent[1]) <= 1) {
+ return;
+ }
+
+ dispatch.brush({extent: extent, brush: brush});
+
+ updateBrushBG();
+ dispatch.onBrush(extent);
+ }
+
+
+ });
+
+ renderWatch.renderEnd('focus immediate');
+ return chart;
+ }
+
+
+ //============================================================
+ // Event Handling/Dispatching (out of chart's scope)
+ //------------------------------------------------------------
+
+ //============================================================
+ // Expose Public Variables
+ //------------------------------------------------------------
+
+ // expose chart's sub-components
+ chart.dispatch = dispatch;
+ chart.content = content;
+ chart.brush = brush;
+ chart.xAxis = xAxis;
+ chart.yAxis = yAxis;
+ chart.options = nv.utils.optionsFunc.bind(chart);
+
+ chart._options = Object.create({}, {
+ // simple options, just get/set the necessary values
+ width: {get: function(){return width;}, set: function(_){width=_;}},
+ height: {get: function(){return height;}, set: function(_){height=_;}},
+ showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
+ showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
+ brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
+
+ // options that require extra logic in the setter
+ margin: {get: function(){return margin;}, set: function(_){
+ margin.top = _.top !== undefined ? _.top : margin.top;
+ margin.right = _.right !== undefined ? _.right : margin.right;
+ margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
+ margin.left = _.left !== undefined ? _.left : margin.left;
+ }},
+ duration: {get: function(){return duration;}, set: function(_){
+ duration = _;
+ renderWatch.reset(duration);
+ content.duration(duration);
+ xAxis.duration(duration);
+ yAxis.duration(duration);
+ }},
+ color: {get: function(){return color;}, set: function(_){
+ color = nv.utils.getColor(_);
+ content.color(color);
+ }},
+ interpolate: {get: function(){return content.interpolate();}, set: function(_){
+ content.interpolate(_);
+ }},
+ xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
+ xAxis.tickFormat(_);
+ }},
+ yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
+ yAxis.tickFormat(_);
+ }},
+ x: {get: function(){return content.x();}, set: function(_){
+ content.x(_);
+ }},
+ y: {get: function(){return content.y();}, set: function(_){
+ content.y(_);
+ }},
+ rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
+ rightAlignYAxis = _;
+ yAxis.orient( rightAlignYAxis ? 'right' : 'left');
+ }},
+ });
+
+ nv.utils.inheritOptions(chart, content);
+ nv.utils.initOptions(chart);
+
+ return chart;
+};
nv.models.forceDirectedGraph = function() {
"use strict";
//============================================================
// Public Variables with Default Settings
@@ -4749,10 +5105,11 @@
var margin = {top: 5, right: 0, bottom: 5, left: 0}
, width = 400
, height = 20
, getKey = function(d) { return d.key }
+ , keyFormatter = function (d) { return d }
, color = nv.utils.getColor()
, maxKeyLength = 20 //default value for key lengths
, align = true
, padding = 28 //define how much space between legend items. - recommend 32 for furious version
, rightAlign = true
@@ -4900,11 +5257,11 @@
series.classed('nv-disabled', function(d) { return d.userDisabled });
series.exit().remove();
seriesText
.attr('fill', setTextColor)
- .text(getKey);
+ .text(function (d) { return keyFormatter(getKey(d)) });
//TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
// NEW ALIGNING CODE, TODO: clean up
var versPadding;
@@ -4919,14 +5276,14 @@
if (align) {
var seriesWidths = [];
series.each(function(d,i) {
var legendText;
- if (getKey(d) && (getKey(d).length > maxKeyLength)) {
- var trimmedKey = getKey(d).substring(0, maxKeyLength);
+ if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {
+ var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);
legendText = d3.select(this).select('text').text(trimmedKey + "...");
- d3.select(this).append("svg:title").text(getKey(d));
+ d3.select(this).append("svg:title").text(keyFormatter(getKey(d)));
} else {
legendText = d3.select(this).select('text');
}
var nodeTextLength;
try {
@@ -5057,21 +5414,22 @@
chart.dispatch = dispatch;
chart.options = nv.utils.optionsFunc.bind(chart);
chart._options = Object.create({}, {
// simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
- align: {get: function(){return align;}, set: function(_){align=_;}},
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
- maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
+ width: {get: function(){return width;}, set: function(_){width=_;}},
+ height: {get: function(){return height;}, set: function(_){height=_;}},
+ key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
+ keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
+ align: {get: function(){return align;}, set: function(_){align=_;}},
+ rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
+ maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
+ padding: {get: function(){return padding;}, set: function(_){padding=_;}},
+ updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
+ radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
+ expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
+ vers: {get: function(){return vers;}, set: function(_){vers=_;}},
// options that require extra logic in the setter
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
@@ -5433,11 +5791,11 @@
g.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
wrap.select('.nv-legendWrap')
@@ -5524,11 +5882,10 @@
});
});
var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
interactiveLayer.tooltip
- .chartContainer(that.parentNode)
.valueFormatter(function(d,i) {
return yAxis.tickFormat()(d);
})
.data({
value: xValue,
@@ -5728,10 +6085,11 @@
var margin = {top: 5, right: 0, bottom: 5, left: 0}
, width = 400
, height = 20
, getKey = function(d) { return d.key }
+ , keyFormatter = function (d) { return d }
, color = nv.utils.getColor()
, maxKeyLength = 20 //default value for key lengths
, align = true
, padding = 32 //define how much space between legend items. - recommend 32 for furious version
, rightAlign = true
@@ -5887,24 +6245,24 @@
series.classed('nv-disabled', function(d) { return d.userDisabled });
series.exit().remove();
seriesText
.attr('fill', setTextColor)
- .text(getKey);
+ .text(function (d) { return keyFormatter(getKey(d)) });
//TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
// NEW ALIGNING CODE, TODO: clean up
var legendWidth = 0;
if (align) {
var seriesWidths = [];
series.each(function(d,i) {
var legendText;
- if (getKey(d) && (getKey(d).length > maxKeyLength)) {
- var trimmedKey = getKey(d).substring(0, maxKeyLength);
+ if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {
+ var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);
legendText = d3.select(this).select('text').text(trimmedKey + "...");
- d3.select(this).append("svg:title").text(getKey(d));
+ d3.select(this).append("svg:title").text(keyFormatter(getKey(d)));
} else {
legendText = d3.select(this).select('text');
}
var nodeTextLength;
try {
@@ -6068,21 +6426,22 @@
chart.dispatch = dispatch;
chart.options = nv.utils.optionsFunc.bind(chart);
chart._options = Object.create({}, {
// simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
- align: {get: function(){return align;}, set: function(_){align=_;}},
+ width: {get: function(){return width;}, set: function(_){width=_;}},
+ height: {get: function(){return height;}, set: function(_){height=_;}},
+ key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
+ keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
+ align: {get: function(){return align;}, set: function(_){align=_;}},
maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
+ rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
+ padding: {get: function(){return padding;}, set: function(_){padding=_;}},
+ updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
+ radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
+ expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
+ vers: {get: function(){return vers;}, set: function(_){vers=_;}},
// options that require extra logic in the setter
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
@@ -6338,18 +6697,14 @@
, xAxis = nv.models.axis()
, yAxis = nv.models.axis()
, legend = nv.models.legend()
, interactiveLayer = nv.interactiveGuideline()
, tooltip = nv.models.tooltip()
- , lines2 = nv.models.line()
- , x2Axis = nv.models.axis()
- , y2Axis = nv.models.axis()
- , brush = d3.svg.brush()
+ , focus = nv.models.focus(nv.models.line())
;
var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , margin2 = {top: 0, right: 20, bottom: 20, left: 60}
, color = nv.utils.defaultColor()
, width = null
, height = null
, showLegend = true
, legendPosition = 'top'
@@ -6357,42 +6712,30 @@
, showYAxis = true
, rightAlignYAxis = false
, useInteractiveGuideline = false
, x
, y
- , x2
- , y2
, focusEnable = false
- , focusShowAxisY = false
- , focusShowAxisX = true
- , focusHeight = 50
- , brushExtent = null
, state = nv.utils.state()
, defaultState = null
, noData = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState', 'renderEnd')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd')
, duration = 250
;
// set options on sub-objects for this chart
xAxis.orient('bottom').tickPadding(7);
yAxis.orient(rightAlignYAxis ? 'right' : 'left');
lines.clipEdge(true).duration(0);
- lines2.interactive(false);
- // We don't want any points emitted for the focus chart's scatter graph.
- lines2.pointActive(function(d) { return false; });
- x2Axis.orient('bottom').tickPadding(5);
- y2Axis.orient(rightAlignYAxis ? 'right' : 'left');
-
tooltip.valueFormatter(function(d, i) {
return yAxis.tickFormat()(d, i);
}).headerFormatter(function(d, i) {
return xAxis.tickFormat()(d, i);
});
-
+
interactiveLayer.tooltip.valueFormatter(function(d, i) {
return yAxis.tickFormat()(d, i);
}).headerFormatter(function(d, i) {
return xAxis.tickFormat()(d, i);
});
@@ -6422,24 +6765,19 @@
};
function chart(selection) {
renderWatch.reset();
renderWatch.models(lines);
- renderWatch.models(lines2);
if (showXAxis) renderWatch.models(xAxis);
if (showYAxis) renderWatch.models(yAxis);
- if (focusShowAxisX) renderWatch.models(x2Axis);
- if (focusShowAxisY) renderWatch.models(y2Axis);
selection.each(function(data) {
var container = d3.select(this);
nv.utils.initSVG(container);
var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0),
- availableHeight2 = focusHeight - margin2.top - margin2.bottom;
-
- chart.update = function() {
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
+ chart.update = function() {
if( duration === 0 ) {
container.call( chart );
} else {
container.transition().duration(duration).call(chart);
}
@@ -6471,16 +6809,18 @@
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
+ /* Update `main' graph on brush update. */
+ focus.dispatch.on("onBrush", function(extent) {
+ onBrush(extent);
+ });
// Setup Scales
x = lines.xScale();
y = lines.yScale();
- x2 = lines2.xScale();
- y2 = lines2.yScale();
// Setup containers and skeleton of chart
var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g');
var g = wrap.select('g');
@@ -6492,17 +6832,11 @@
focusEnter.append('g').attr('class', 'nv-x nv-axis');
focusEnter.append('g').attr('class', 'nv-y nv-axis');
focusEnter.append('g').attr('class', 'nv-linesWrap');
focusEnter.append('g').attr('class', 'nv-interactive');
- var contextEnter = gEnter.append('g').attr('class', 'nv-context');
- contextEnter.append('g').attr('class', 'nv-background').append('rect');
- contextEnter.append('g').attr('class', 'nv-x nv-axis');
- contextEnter.append('g').attr('class', 'nv-y nv-axis');
- contextEnter.append('g').attr('class', 'nv-linesWrap');
- contextEnter.append('g').attr('class', 'nv-brushBackground');
- contextEnter.append('g').attr('class', 'nv-x nv-brush');
+ var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');
// Legend
if (!showLegend) {
g.select('.nv-legendWrap').selectAll('*').remove();
} else {
@@ -6512,15 +6846,15 @@
.datum(data)
.call(legend);
if (legendPosition === 'bottom') {
wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (availableHeight1) +')');
+ .attr('transform', 'translate(0,' + availableHeight +')');
} else if (legendPosition === 'top') {
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0);
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
}
wrap.select('.nv-legendWrap')
.attr('transform', 'translate(0,' + (-margin.top) +')');
}
@@ -6535,27 +6869,26 @@
//Set up interactive layer
if (useInteractiveGuideline) {
interactiveLayer
.width(availableWidth)
- .height(availableHeight1)
+ .height(availableHeight)
.margin({left:margin.left, top:margin.top})
.svgContainer(container)
.xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
g.select('.nv-focus .nv-background rect')
.attr('width', availableWidth)
- .attr('height', availableHeight1);
-
+ .attr('height', availableHeight);
+
lines
.width(availableWidth)
- .height(availableHeight1)
+ .height(availableHeight)
.color(data.map(function(d,i) {
return d.color || color(d, i);
-
}).filter(function(d,i) { return !data[i].disabled; }));
var linesWrap = g.select('.nv-linesWrap')
.datum(data.filter(function(d) { return !d.disabled; }));
@@ -6563,18 +6896,17 @@
// Setup Main (Focus) Axes
if (showXAxis) {
xAxis
.scale(x)
._ticks(nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight1, 0);
-
+ .tickSize(-availableHeight, 0);
}
if (showYAxis) {
yAxis
.scale(y)
- ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
+ ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
.tickSize( -availableWidth, 0);
}
//============================================================
// Update Axes
@@ -6596,108 +6928,32 @@
.duration(duration)
.call(yAxis)
;
}
}
-
+
g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight1 + ')');
+ .attr('transform', 'translate(0,' + availableHeight + ')');
- if( !focusEnable )
- {
+ //============================================================
+ // Update Focus
+ //============================================================
+ if(!focusEnable) {
linesWrap.call(lines);
updateXAxis();
updateYAxis();
- }
- else
- {
- lines2
- .defined(lines.defined())
- .width(availableWidth)
- .height(availableHeight2)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled; }));
-
- g.select('.nv-context')
- .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
- .style('display', focusEnable ? 'initial' : 'none')
- ;
-
- var contextLinesWrap = g.select('.nv-context .nv-linesWrap')
+ } else {
+ focus.width(availableWidth);
+ g.select('.nv-focusWrap')
+ .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')
.datum(data.filter(function(d) { return !d.disabled; }))
- ;
-
- d3.transition(contextLinesWrap).call(lines2);
-
-
- // Setup Brush
- brush
- .x(x2)
- .on('brush', function() {
- onBrush();
- });
-
- if (brushExtent) brush.extent(brushExtent);
-
- var brushBG = g.select('.nv-brushBackground').selectAll('g')
- .data([brushExtent || brush.extent()]);
-
- var brushBGenter = brushBG.enter()
- .append('g');
-
- brushBGenter.append('rect')
- .attr('class', 'left')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- brushBGenter.append('rect')
- .attr('class', 'right')
- .attr('x', 0)
- .attr('y', 0)
- .attr('height', availableHeight2);
-
- var gBrush = g.select('.nv-x.nv-brush')
- .call(brush);
- gBrush.selectAll('rect')
- .attr('height', availableHeight2);
- gBrush.selectAll('.resize').append('path').attr('d', resizePath);
-
- onBrush();
-
- g.select('.nv-context .nv-background rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight2);
-
- // Setup Secondary (Context) Axes
- if (focusShowAxisX) {
- x2Axis
- .scale(x2)
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
- .tickSize(-availableHeight2, 0);
-
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
- d3.transition(g.select('.nv-context .nv-x.nv-axis'))
- .call(x2Axis);
+ .call(focus);
+ var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();
+ if(extent !== null){
+ onBrush(extent);
}
-
- if (focusShowAxisY) {
- y2Axis
- .scale(y2)
- ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) )
- .tickSize( -availableWidth, 0);
-
- d3.transition(g.select('.nv-context .nv-y.nv-axis'))
- .call(y2Axis);
- }
-
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
}
-
//============================================================
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
legend.dispatch.on('stateChange', function(newState) {
@@ -6714,11 +6970,11 @@
.filter(function(series, i) {
series.seriesIndex = i;
return !series.disabled && !series.disableTooltip;
})
.forEach(function(series,i) {
- var extent = focusEnable ? (brush.empty() ? x2.domain() : brush.extent()) : x.domain();
+ var extent = focusEnable ? (focus.brush.empty() ? focus.xScale().domain() : focus.brush.extent()) : x.domain();
var currentValues = series.values.filter(function(d,i) {
return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
});
pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x());
@@ -6750,11 +7006,10 @@
var defaultValueFormatter = function(d,i) {
return d == null ? "N/A" : yAxis.tickFormat()(d);
};
interactiveLayer.tooltip
- .chartContainer(chart.container.parentNode)
.valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)
.data({
value: chart.x()( singlePoint,pointIndex ),
index: pointIndex,
series: allData
@@ -6798,71 +7053,38 @@
series.disabled = e.disabled[i];
});
state.disabled = e.disabled;
}
-
chart.update();
});
//============================================================
// Functions
//------------------------------------------------------------
-
+
// Taken from crossfilter (http://square.github.com/crossfilter/)
function resizePath(d) {
var e = +(d == 'e'),
x = e ? 1 : -1,
- y = availableHeight2 / 3;
+ y = availableHeight / 3;
return 'M' + (0.5 * x) + ',' + y
+ 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
+ 'V' + (2 * y - 6)
+ 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y)
+ 'Z'
+ 'M' + (2.5 * x) + ',' + (y + 8)
+ 'V' + (2 * y - 8)
+ 'M' + (4.5 * x) + ',' + (y + 8)
+ 'V' + (2 * y - 8);
}
-
-
- function updateBrushBG() {
- if (!brush.empty()) brush.extent(brushExtent);
- brushBG
- .data([brush.empty() ? x2.domain() : brushExtent])
- .each(function(d,i) {
- var leftWidth = x2(d[0]) - x.range()[0],
- rightWidth = availableWidth - x2(d[1]);
- d3.select(this).select('.left')
- .attr('width', leftWidth < 0 ? 0 : leftWidth);
-
- d3.select(this).select('.right')
- .attr('x', x2(d[1]))
- .attr('width', rightWidth < 0 ? 0 : rightWidth);
- });
- }
-
-
- function onBrush() {
- brushExtent = brush.empty() ? null : brush.extent();
- var extent = brush.empty() ? x2.domain() : brush.extent();
-
- //The brush extent cannot be less than one. If it is, don't update the line chart.
- if (Math.abs(extent[0] - extent[1]) <= 1) {
- return;
- }
-
- dispatch.brush({extent: extent, brush: brush});
-
-
- updateBrushBG();
-
+
+ function onBrush(extent) {
// Update Main (Focus)
var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
.datum(
- data
- .filter(function(d) { return !d.disabled; })
+ data.filter(function(d) { return !d.disabled; })
.map(function(d,i) {
return {
key: d.key,
area: d.area,
classed: d.classed,
@@ -6872,18 +7094,15 @@
disableTooltip: d.disableTooltip
};
})
);
focusLinesWrap.transition().duration(duration).call(lines);
-
-
+
// Update Main (Focus) Axes
updateXAxis();
updateYAxis();
}
-
-
});
renderWatch.renderEnd('lineChart immediate');
return chart;
}
@@ -6908,16 +7127,16 @@
//------------------------------------------------------------
// expose chart's sub-components
chart.dispatch = dispatch;
chart.lines = lines;
- chart.lines2 = lines2;
chart.legend = legend;
+ chart.focus = focus;
chart.xAxis = xAxis;
- chart.x2Axis = x2Axis;
+ chart.x2Axis = focus.xAxis
chart.yAxis = yAxis;
- chart.y2Axis = y2Axis;
+ chart.y2Axis = focus.yAxis
chart.interactiveLayer = interactiveLayer;
chart.tooltip = tooltip;
chart.state = state;
chart.dispatch = dispatch;
chart.options = nv.utils.optionsFunc.bind(chart);
@@ -6928,64 +7147,65 @@
height: {get: function(){return height;}, set: function(_){height=_;}},
showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
- focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
- focusHeight: {get: function(){return height2;}, set: function(_){focusHeight=_;}},
- focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}},
- focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}},
- brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
noData: {get: function(){return noData;}, set: function(_){noData=_;}},
+ // Focus options, mostly passed onto focus model.
+ focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
+ focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},
+ focusShowAxisX: {get: function(){return focus.showXAxis();}, set: function(_){focus.showXAxis(_);}},
+ focusShowAxisY: {get: function(){return focus.showYAxis();}, set: function(_){focus.showYAxis(_);}},
+ brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},
// options that require extra logic in the setter
+ focusMargin: {get: function(){return focus.margin}, set: function(_){
+ focus.margin.top = _.top !== undefined ? _.top : focus.margin.top;
+ focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;
+ focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;
+ focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;
+ }},
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
margin.left = _.left !== undefined ? _.left : margin.left;
}},
duration: {get: function(){return duration;}, set: function(_){
duration = _;
renderWatch.reset(duration);
lines.duration(duration);
+ focus.duration(duration);
xAxis.duration(duration);
- x2Axis.duration(duration);
yAxis.duration(duration);
- y2Axis.duration(duration);
}},
- focusMargin: {get: function(){return margin2;}, set: function(_){
- margin2.top = _.top !== undefined ? _.top : margin2.top;
- margin2.right = _.right !== undefined ? _.right : margin2.right;
- margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom;
- margin2.left = _.left !== undefined ? _.left : margin2.left;
- }},
color: {get: function(){return color;}, set: function(_){
color = nv.utils.getColor(_);
legend.color(color);
lines.color(color);
+ focus.color(color);
}},
interpolate: {get: function(){return lines.interpolate();}, set: function(_){
lines.interpolate(_);
- lines2.interpolate(_);
+ focus.interpolate(_);
}},
xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
xAxis.tickFormat(_);
- x2Axis.tickFormat(_);
+ focus.xTickFormat(_);
}},
yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
yAxis.tickFormat(_);
- y2Axis.tickFormat(_);
+ focus.yTickFormat(_);
}},
x: {get: function(){return lines.x();}, set: function(_){
lines.x(_);
- lines2.x(_);
+ focus.x(_);
}},
y: {get: function(){return lines.y();}, set: function(_){
lines.y(_);
- lines2.y(_);
+ focus.y(_);
}},
rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
rightAlignYAxis = _;
yAxis.orient( rightAlignYAxis ? 'right' : 'left');
}},
@@ -7004,13 +7224,14 @@
return chart;
};
nv.models.lineWithFocusChart = function() {
return nv.models.lineChart()
- .margin({ bottom: 30 })
+ .margin({ bottom: 30 })
.focusEnable( true );
-};nv.models.linePlusBarChart = function() {
+};
+nv.models.linePlusBarChart = function() {
"use strict";
//============================================================
// Public Variables with Default Settings
//------------------------------------------------------------
@@ -7078,17 +7299,17 @@
//============================================================
// Private Variables
//------------------------------------------------------------
var getBarsAxis = function() {
- return !switchYAxisOrder
+ return switchYAxisOrder
? { main: y2Axis, focus: y4Axis }
: { main: y1Axis, focus: y3Axis }
}
var getLinesAxis = function() {
- return !switchYAxisOrder
+ return switchYAxisOrder
? { main: y1Axis, focus: y3Axis }
: { main: y2Axis, focus: y4Axis }
}
var stateGetter = function(data) {
@@ -7240,11 +7461,11 @@
}
return series;
}))
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
// FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"?
availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight;
}
@@ -7458,10 +7679,11 @@
.filter(function(dataLine) { return !dataLine.disabled; })
.map(function(d,i) {
return {
area: d.area,
fillOpacity: d.fillOpacity,
+ strokeWidth: d.strokeWidth,
key: d.key,
values: d.values.filter(function(d,i) {
return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
})
}
@@ -7701,10 +7923,11 @@
, xDomain
, yDomain
, xRange
, yRange
, groupSpacing = 0.1
+ , fillOpacity = 0.75
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
;
//============================================================
// Private Variables
@@ -7883,11 +8106,11 @@
.classed('hover', function(d) { return d.hover })
.style('fill', function(d,i){ return color(d, i) })
.style('stroke', function(d,i){ return color(d, i) });
groups
.style('stroke-opacity', 1)
- .style('fill-opacity', 0.75);
+ .style('fill-opacity', fillOpacity);
var bars = groups.selectAll('rect.nv-bar')
.data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
bars.exit().remove();
@@ -8074,10 +8297,11 @@
clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}},
disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},
id: {get: function(){return id;}, set: function(_){id=_;}},
hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}},
groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
+ fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},
// options that require extra logic in the setter
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
@@ -8267,11 +8491,11 @@
g.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
g.select('.nv-legendWrap')
@@ -8474,11 +8698,10 @@
data: series.values[pointIndex]
});
});
interactiveLayer.tooltip
- .chartContainer(that.parentNode)
.data({
value: xValue,
index: pointIndex,
series: allData
})();
@@ -8609,10 +8832,11 @@
, stacked = false
, showValues = false
, showBarLabels = false
, valuePadding = 60
, groupSpacing = 0.1
+ , fillOpacity = 0.75
, valueFormat = d3.format(',.2f')
, delay = 1200
, xDomain
, yDomain
, xRange
@@ -8716,11 +8940,11 @@
.classed('hover', function(d) { return d.hover })
.style('fill', function(d,i){ return color(d, i) })
.style('stroke', function(d,i){ return color(d, i) });
groups.watchTransition(renderWatch, 'multibarhorizontal: groups')
.style('stroke-opacity', 1)
- .style('fill-opacity', .75);
+ .style('fill-opacity', fillOpacity);
var bars = groups.selectAll('g.nv-bar')
.data(function(d) { return d.values });
bars.exit().remove();
@@ -8917,11 +9141,12 @@
//showBarLabels: {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}},
disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}},
id: {get: function(){return id;}, set: function(_){id=_;}},
valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}},
- groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
+ groupSpacing: {get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
+ fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},
// options that require extra logic in the setter
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
@@ -9102,11 +9327,11 @@
g.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
g.select('.nv-legendWrap')
@@ -9458,11 +9683,11 @@
series.key = series.originalKey + (series.yAxis == 1 ? '' : legendRightAxisHint);
return series;
}))
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
g.select('.legendWrap')
@@ -9738,25 +9963,26 @@
data: point,
yAxis: series.yAxis == 2 ? yAxis2 : yAxis1
});
});
- interactiveLayer.tooltip
- .chartContainer(chart.container.parentNode)
- .headerFormatter(function(d, i) {
- return xAxis.tickFormat()(d, i);
- })
- .valueFormatter(function(d,i) {
+ var defaultValueFormatter = function(d,i) {
var yAxis = allData[i].yAxis;
- return d === null ? "N/A" : yAxis.tickFormat()(d);
- })
- .data({
- value: chart.x()( singlePoint,pointIndex ),
- index: pointIndex,
- series: allData
- })();
+ return d == null ? "N/A" : yAxis.tickFormat()(d);
+ };
+ interactiveLayer.tooltip
+ .headerFormatter(function(d, i) {
+ return xAxis.tickFormat()(d, i);
+ })
+ .valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)
+ .data({
+ value: chart.x()( singlePoint,pointIndex ),
+ index: pointIndex,
+ series: allData
+ })();
+
interactiveLayer.renderGuideLine(pointXLocation);
});
interactiveLayer.dispatch.on("elementMouseout",function(e) {
clearHighlights();
@@ -10199,23 +10425,23 @@
var dataValues = data.map(function (d) {return d.values});
if (active.length === 0) {
active = data;
}; //set all active before first brush call
-
+
dimensionNames = dimensionData.sort(function (a, b) { return a.currentPosition - b.currentPosition; }).map(function (d) { return d.key });
enabledDimensions = dimensionData.filter(function (d) { return !d.disabled; });
-
+
// Setup Scales
x.rangePoints([0, availableWidth], 1).domain(enabledDimensions.map(function (d) { return d.key; }));
//Set as true if all values on an axis are missing.
// Extract the list of dimensions and create a scale for each.
var oldDomainMaxValue = {};
var displayMissingValuesline = false;
var currentTicks = [];
-
+
dimensionNames.forEach(function(d) {
var extent = d3.extent(dataValues, function (p) { return +p[d]; });
var min = extent[0];
var max = extent[1];
var onlyUndefinedValues = false;
@@ -10288,11 +10514,11 @@
missingValuesline.exit().remove();
missingValuesline.attr("x1", function(d) { return d[0]; })
.attr("y1", function(d) { return d[1]; })
.attr("x2", function(d) { return d[2]; })
.attr("y2", function(d) { return d[3]; });
-
+
//Add the text "undefined values" under the missing value line
missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data([undefinedValuesLabel]);
missingValueslineText.append('text').data([undefinedValuesLabel]);
missingValueslineText.enter().append('text');
missingValueslineText.exit().remove();
@@ -10354,11 +10580,11 @@
.attr('dy', '-1em')
.attr('text-anchor', 'middle')
.on("mouseover", function(d, i) {
dispatch.elementMouseover({
label: d.tooltip || d.key,
- color: d.color
+ color: d.color
});
})
.on("mouseout", function(d, i) {
dispatch.elementMouseout({
label: d.tooltip
@@ -10445,32 +10671,32 @@
f.extent[0] = brushDomain[0];
}
if (visible)
y[f.dimension].brush.extent(f.extent);
});
-
+
dimensions.select('.nv-brushBackground')
.each(function (d) {
d3.select(this).call(y[d.key].brush);
})
.selectAll('rect')
.attr('x', -8)
.attr('width', 16);
-
+
updateTicks();
}
-
+
// Handles a brush event, toggling the display of foreground lines.
function brushstart() {
//If brush aren't visible, show it before brushing again.
if (displayBrush === false) {
displayBrush = true;
restoreBrush(true);
}
}
-
+
// Handles a brush event, toggling the display of foreground lines.
function brush() {
actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); });
extents = actives.map(function(p) { return y[p].brush.extent(); });
@@ -10491,13 +10717,13 @@
return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p]));
});
if (isActive) active.push(d);
return isActive ? null : 'none';
});
-
+
updateTicks();
-
+
dispatch.brush({
filters: filters,
active: active
});
}
@@ -10508,27 +10734,27 @@
f.hasNaN = true;
if (f.extent[1] < y[f.dimension].domain()[0])
f.hasOnlyNaN = true;
});
dispatch.brushEnd(active, hasActiveBrush);
- }
+ }
function updateTicks() {
dimensions.select('.nv-axis')
.each(function (d, i) {
var f = filters.filter(function (k) { return k.dimension == d.key; });
currentTicks[d.key] = y[d.key].domain();
-
+
//If brush are available, display brush extent
if (f.length != 0 && displayBrush)
{
currentTicks[d.key] = [];
- if (f[0].extent[1] > y[d.key].domain()[0])
+ if (f[0].extent[1] > y[d.key].domain()[0])
currentTicks[d.key] = [f[0].extent[1]];
if (f[0].extent[0] >= y[d.key].domain()[0])
- currentTicks[d.key].push(f[0].extent[0]);
+ currentTicks[d.key].push(f[0].extent[0]);
}
-
+
d3.select(this).call(axis.scale(y[d.key]).tickFormat(d.format).tickValues(currentTicks[d.key]));
});
}
function dragStart(d) {
dragging[d.key] = this.parentNode.__origin__ = x(d.key);
@@ -10577,11 +10803,11 @@
displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } },
filters: { get: function () { return filters; }, set: function (_) { filters = _; } },
active: { get: function () { return active; }, set: function (_) { active = _; } },
lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}},
undefinedValuesLabel : {get: function(){return undefinedValuesLabel;}, set: function(_){undefinedValuesLabel=_;}},
-
+
// deprecated options
dimensions: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) {
// deprecated after 1.8.1
nv.deprecated('dimensions', 'use dimensionData instead');
if (dimensionData.length === 0) {
@@ -10597,11 +10823,11 @@
if (dimensionData.length === 0) {
_.forEach(function (k) { dimensionData.push({ key: k }) })
} else {
_.forEach(function (k, i) { dimensionData[i].key = k })
}
-
+
}},
dimensionFormats: {get: function () { return dimensionData.map(function (d) { return d.format }); }, set: function (_) {
// deprecated after 1.8.1
nv.deprecated('dimensionFormats', 'use dimensionData instead');
if (dimensionData.length === 0) {
@@ -10650,11 +10876,11 @@
, dispatch = d3.dispatch('dimensionsOrder', 'brushEnd', 'stateChange', 'changeState', 'renderEnd')
, controlWidth = function () { return showControls ? 180 : 0 }
;
//============================================================
-
+
//============================================================
// Private Variables
//------------------------------------------------------------
var renderWatch = nv.utils.renderWatch(dispatch);
@@ -10677,22 +10903,22 @@
}
};
tooltip.contentGenerator(function(data) {
var str = '<table><thead><tr><td class="legend-color-guide"><div style="background-color:' + data.color + '"></div></td><td><strong>' + data.key + '</strong></td></tr></thead>';
- if(data.series.length !== 0)
+ if(data.series.length !== 0)
{
str = str + '<tbody><tr><td height ="10px"></td></tr>';
data.series.forEach(function(d){
str = str + '<tr><td class="legend-color-guide"><div style="background-color:' + d.color + '"></div></td><td class="key">' + d.key + '</td><td class="value">' + d.value + '</td></tr>';
- });
+ });
str = str + '</tbody>';
}
str = str + '</table>';
return str;
});
-
+
//============================================================
// Chart function
//------------------------------------------------------------
function chart(selection) {
@@ -10741,19 +10967,19 @@
nv.utils.noData(chart, container);
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
-
+
//------------------------------------------------------------
// Setup containers and skeleton of chart
var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinatesChart').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinatesChart').append('g');
var g = wrap.select('g');
-
+
gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
g.select("rect")
.attr("width", availableWidth)
@@ -10768,11 +10994,11 @@
g.select('.nv-legendWrap')
.datum(dimensionData.sort(function (a, b) { return a.originalPosition - b.originalPosition; }))
.call(legend);
- if (margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
wrap.select('.nv-legendWrap')
.attr('transform', 'translate( 0 ,' + (-margin.top) + ')');
@@ -10783,16 +11009,16 @@
parallelCoordinates
.width(availableWidth)
.height(availableHeight)
.dimensionData(dimensionData)
.displayBrush(displayBrush);
-
+
var parallelCoordinatesWrap = g.select('.nv-parallelCoordinatesWrap ')
.datum(data);
parallelCoordinatesWrap.transition().call(parallelCoordinates);
-
+
//============================================================
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
//Display reset brush button
parallelCoordinates.dispatch.on('brushEnd', function (active, hasActiveBrush) {
@@ -10849,11 +11075,11 @@
parallelCoordinates.dispatch.on('elementMouseover.tooltip', function (evt) {
var tp = {
key: evt.label,
color: evt.color,
series: []
- }
+ }
if(evt.values){
Object.keys(evt.values).forEach(function (d) {
var dim = evt.dimensions.filter(function (dd) {return dd.key === d;})[0];
if(dim){
var v;
@@ -10878,11 +11104,11 @@
tooltip();
});
//============================================================
// Expose Public Variables
//------------------------------------------------------------
-
+
// expose chart's sub-components
chart.dispatch = dispatch;
chart.parallelCoordinates = parallelCoordinates;
chart.legend = legend;
chart.tooltip = tooltip;
@@ -10896,11 +11122,11 @@
defaultState: { get: function () { return defaultState; }, set: function (_) { defaultState = _; } },
dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } },
displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } },
noData: { get: function () { return noData; }, set: function (_) { noData = _; } },
nanValue: { get: function () { return nanValue; }, set: function (_) { nanValue = _; } },
-
+
// options that require extra logic in the setter
margin: {
get: function () { return margin; },
set: function (_) {
margin.top = _.top !== undefined ? _.top : margin.top;
@@ -10949,10 +11175,11 @@
, startAngle = false
, padAngle = false
, endAngle = false
, cornerRadius = 0
, donutRatio = 0.5
+ , duration = 250
, arcsRadius = []
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
;
var arcs = [];
@@ -11088,11 +11315,12 @@
.attr("d", arcsOver[i]);
}
dispatch.elementMouseover({
data: d.data,
index: i,
- color: d3.select(this).style("fill")
+ color: d3.select(this).style("fill"),
+ percent: (d.endAngle - d.startAngle) / (2 * Math.PI)
});
});
ae.on('mouseout', function(d, i) {
d3.select(this).classed('hover', false);
if (growOnHover) {
@@ -11130,10 +11358,11 @@
this._current = d;
});
slices.select('path')
.transition()
+ .duration(duration)
.attr('d', function (d, i) { return arcs[i](d); })
.attrTween('d', arcTween);
if (showLabels) {
// This does the normal label
@@ -11334,10 +11563,14 @@
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
}},
+ duration: {get: function(){return duration;}, set: function(_){
+ duration = _;
+ renderWatch.reset(duration);
+ }},
y: {get: function(){return getY;}, set: function(_){
getY=d3.functor(_);
}},
color: {get: function(){return color;}, set: function(_){
color=nv.utils.getColor(_);
@@ -11362,10 +11595,11 @@
var tooltip = nv.models.tooltip();
var margin = {top: 30, right: 20, bottom: 20, left: 20}
, width = null
, height = null
+ , showTooltipPercent = false
, showLegend = true
, legendPosition = "top"
, color = nv.utils.defaultColor()
, state = nv.utils.state()
, defaultState = null
@@ -11467,11 +11701,11 @@
wrap.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
wrap.select('.nv-legendWrap')
@@ -11532,12 +11766,17 @@
pie.dispatch.on('elementMouseover.tooltip', function(evt) {
evt['series'] = {
key: chart.x()(evt.data),
value: chart.y()(evt.data),
- color: evt.color
+ color: evt.color,
+ percent: evt.percent
};
+ if (!showTooltipPercent) {
+ delete evt.percent;
+ delete evt.series.percent;
+ }
tooltip.data(evt).hidden(false);
});
pie.dispatch.on('elementMouseout.tooltip', function(evt) {
tooltip.hidden(true);
@@ -11559,26 +11798,28 @@
chart.options = nv.utils.optionsFunc.bind(chart);
// use Object get/set functionality to map between vars and chart functions
chart._options = Object.create({}, {
// simple options, just get/set the necessary values
- width: {get: function(){return width;}, set: function(_){width=_;}},
- height: {get: function(){return height;}, set: function(_){height=_;}},
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
- legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
+ width: {get: function(){return width;}, set: function(_){width=_;}},
+ height: {get: function(){return height;}, set: function(_){height=_;}},
+ noData: {get: function(){return noData;}, set: function(_){noData=_;}},
+ showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},
+ showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
+ legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
+ defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
// options that require extra logic in the setter
color: {get: function(){return color;}, set: function(_){
color = _;
legend.color(color);
pie.color(color);
}},
duration: {get: function(){return duration;}, set: function(_){
duration = _;
renderWatch.reset(duration);
+ pie.duration(duration);
}},
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
@@ -11630,11 +11871,11 @@
, singlePoint = false
, dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd')
, useVoronoi = true
, duration = 250
, interactiveUpdateDelay = 300
- , showLabels = false
+ , showLabels = false
;
//============================================================
// Private Variables
@@ -11688,11 +11929,11 @@
point.series = i;
});
});
// Setup Scales
- var logScale = chart.yScale().name === d3.scale.log().name ? true : false;
+ var logScale = chart.yScale().name === d3.scale.log().name ? true : false;
// remap and flatten the data for use in calculating the scales' domains
var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance
d3.merge(
data.map(function(d) {
return d.values.map(function(d,i) {
@@ -11924,18 +12165,20 @@
.on('click', function(d,i) {
//nv.log('test', d, i);
if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
var series = data[d.series],
point = series.values[i];
-
+ var element = this;
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page
relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
seriesIndex: d.series,
- pointIndex: i
+ pointIndex: i,
+ event: d3.event,
+ element: element
});
})
.on('dblclick', function(d,i) {
if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
var series = data[d.series],
@@ -12046,14 +12289,14 @@
.attr('d',
nv.utils.symbol()
.type(function(d) { return getShape(d[0]); })
.size(function(d) { return z(getSize(d[0],d[1])) })
);
-
- // add label a label to scatter chart
+
+ // add label a label to scatter chart
if(showLabels)
- {
+ {
var titles = groups.selectAll('.nv-label')
.data(function(d) {
return d.values.map(
function (point, pointIndex) {
return [point, pointIndex]
@@ -12062,11 +12305,11 @@
return pointActive(pointArray[0], pointIndex)
})
});
titles.enter().append('text')
- .style('fill', function (d,i) {
+ .style('fill', function (d,i) {
return d.color })
.style('stroke-opacity', 0)
.style('fill-opacity', 1)
.attr('transform', function(d) {
var dx = nv.utils.NaNtoZero(x0(getX(d[0],d[1]))) + Math.sqrt(z(getSize(d[0],d[1]))/Math.PI) + 2;
@@ -12375,11 +12618,11 @@
wrap.select('.nv-legendWrap')
.datum(data)
.call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
wrap.select('.nv-legendWrap')
@@ -12629,11 +12872,11 @@
//============================================================
// Private Variables
//------------------------------------------------------------
var renderWatch = nv.utils.renderWatch(dispatch);
-
+
function chart(selection) {
renderWatch.reset();
selection.each(function(data) {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom;
@@ -12694,11 +12937,11 @@
.attr('class', function(d,i) {
return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
});
});
-
+
renderWatch.renderEnd('sparkline immediate');
return chart;
}
//============================================================
@@ -12764,11 +13007,11 @@
, alignValue = true
, rightAlignValue = false
, noData = null
, dispatch = d3.dispatch('renderEnd')
;
-
+
//============================================================
// Private Variables
//------------------------------------------------------------
var renderWatch = nv.utils.renderWatch(dispatch);
@@ -13058,17 +13301,17 @@
gEnter.append('g').attr('class', 'nv-areaWrap');
gEnter.append('g').attr('class', 'nv-scatterWrap');
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
+
// If the user has not specified forceY, make sure 0 is included in the domain
// Otherwise, use user-specified values for forceY
if (scatter.forceY().length == 0) {
scatter.forceY().push(0);
}
-
+
scatter
.width(availableWidth)
.height(availableHeight)
.x(getX)
.y(function(d) {
@@ -13302,10 +13545,11 @@
, yAxis = nv.models.axis()
, legend = nv.models.legend()
, controls = nv.models.legend()
, interactiveLayer = nv.interactiveGuideline()
, tooltip = nv.models.tooltip()
+ , focus = nv.models.focus(nv.models.stackedArea())
;
var margin = {top: 30, right: 25, bottom: 50, left: 60}
, width = null
, height = null
@@ -13313,10 +13557,11 @@
, showControls = true
, showLegend = true
, showXAxis = true
, showYAxis = true
, rightAlignYAxis = false
+ , focusEnable = false
, useInteractiveGuideline = false
, showTotalInTooltip = true
, totalLabel = 'TOTAL'
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
@@ -13345,11 +13590,11 @@
interactiveLayer.tooltip
.headerFormatter(function(d, i) {
return xAxis.tickFormat()(d, i);
})
.valueFormatter(function(d, i) {
- return yAxis.tickFormat()(d, i);
+ return d == null ? "N/A" : yAxis.tickFormat()(d, i);
});
var oldYTickFormat = null,
oldValueFormatter = null;
@@ -13394,11 +13639,11 @@
var container = d3.select(this),
that = this;
nv.utils.initSVG(container);
var availableWidth = nv.utils.availableWidth(width, container, margin),
- availableHeight = nv.utils.availableHeight(height, container, margin);
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
chart.update = function() { container.transition().duration(duration).call(chart); };
chart.container = this;
state
@@ -13425,42 +13670,45 @@
nv.utils.noData(chart, container)
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
-
// Setup Scales
x = stacked.xScale();
y = stacked.yScale();
// Setup containers and skeleton of chart
var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');
var g = wrap.select('g');
- gEnter.append("rect").style("opacity",0);
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-stackedWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
- gEnter.append('g').attr('class', 'nv-interactive');
- g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
+ var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
+ focusEnter.append('g').attr('class', 'nv-background').append('rect');
+ focusEnter.append('g').attr('class', 'nv-x nv-axis');
+ focusEnter.append('g').attr('class', 'nv-y nv-axis');
+ focusEnter.append('g').attr('class', 'nv-stackedWrap');
+ focusEnter.append('g').attr('class', 'nv-interactive');
+ // g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
+
+ var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');
+
// Legend
if (!showLegend) {
g.select('.nv-legendWrap').selectAll('*').remove();
} else {
var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth;
legend.width(legendWidth);
g.select('.nv-legendWrap').datum(data).call(legend);
- if ( margin.top != legend.height()) {
+ if (legend.height() > margin.top) {
margin.top = legend.height();
- availableHeight = nv.utils.availableHeight(height, container, margin);
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
}
g.select('.nv-legendWrap')
.attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');
}
@@ -13507,11 +13755,11 @@
g.select('.nv-controlsWrap')
.datum(controlsData)
.call(controls);
- if ( margin.top != Math.max(controls.height(), legend.height()) ) {
+ if (Math.max(controls.height(), legend.height()) > margin.top) {
margin.top = Math.max(controls.height(), legend.height());
availableHeight = nv.utils.availableHeight(height, container, margin);
}
g.select('.nv-controlsWrap')
@@ -13534,31 +13782,29 @@
.svgContainer(container)
.xScale(x);
wrap.select(".nv-interactive").call(interactiveLayer);
}
+ g.select('.nv-focus .nv-background rect')
+ .attr('width', availableWidth)
+ .attr('height', availableHeight);
+
stacked
.width(availableWidth)
- .height(availableHeight);
+ .height(availableHeight)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled; }));
- var stackedWrap = g.select('.nv-stackedWrap')
- .datum(data);
+ var stackedWrap = g.select('.nv-focus .nv-stackedWrap')
+ .datum(data.filter(function(d) { return !d.disabled; }));
- stackedWrap.transition().call(stacked);
-
// Setup Axes
if (showXAxis) {
xAxis.scale(x)
._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
.tickSize( -availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
-
- g.select('.nv-x.nv-axis')
- .transition().duration(0)
- .call(xAxis);
}
if (showYAxis) {
var ticks;
if (stacked.offset() === 'wiggle') {
@@ -13568,11 +13814,28 @@
ticks = nv.utils.calcTicksY(availableHeight/36, data);
}
yAxis.scale(y)
._ticks(ticks)
.tickSize(-availableWidth, 0);
+ }
+ //============================================================
+ // Update Axes
+ //============================================================
+ function updateXAxis() {
+ if(showXAxis) {
+ g.select('.nv-focus .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + availableHeight + ')')
+ .transition()
+ .duration(duration)
+ .call(xAxis)
+ ;
+ }
+ }
+
+ function updateYAxis() {
+ if(showYAxis) {
if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
var currentFormat = yAxis.tickFormat();
if ( !oldYTickFormat || currentFormat !== percentFormatter )
oldYTickFormat = currentFormat;
@@ -13585,16 +13848,36 @@
yAxis.tickFormat(oldYTickFormat);
oldYTickFormat = null;
}
}
- g.select('.nv-y.nv-axis')
+ g.select('.nv-focus .nv-y.nv-axis')
.transition().duration(0)
.call(yAxis);
+ }
}
//============================================================
+ // Update Focus
+ //============================================================
+ if(!focusEnable) {
+ stackedWrap.transition().call(stacked);
+ updateXAxis();
+ updateYAxis();
+ } else {
+ focus.width(availableWidth);
+ g.select('.nv-focusWrap')
+ .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')
+ .datum(data.filter(function(d) { return !d.disabled; }))
+ .call(focus);
+ var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();
+ if(extent !== null){
+ onBrush(extent);
+ }
+ }
+
+ //============================================================
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
stacked.dispatch.on('areaClick.toggle', function(e) {
if (data.filter(function(d) { return !d.disabled }).length === 1)
@@ -13637,11 +13920,11 @@
chart.update();
});
interactiveLayer.dispatch.on('elementMousemove', function(e) {
stacked.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0;
+ var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0, allNullValues = true;
data
.filter(function(series, i) {
series.seriesIndex = i;
return !series.disabled;
})
@@ -13663,12 +13946,13 @@
value: tooltipValue,
color: color(series,series.seriesIndex),
point: point
});
- if (showTotalInTooltip && stacked.style() != 'expand') {
+ if (showTotalInTooltip && stacked.style() != 'expand' && tooltipValue != null) {
valueSum += tooltipValue;
+ allNullValues = false;
};
});
allData.reverse();
@@ -13692,11 +13976,11 @@
if (indexToHighlight != null)
allData[indexToHighlight].highlight = true;
}
//If we are not in 'expand' mode, add a 'Total' row to the tooltip.
- if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2) {
+ if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2 && !allNullValues) {
allData.push({
key: totalLabel,
value: valueSum,
total: true
});
@@ -13719,11 +14003,10 @@
oldValueFormatter = null;
}
}
interactiveLayer.tooltip
- .chartContainer(that.parentNode)
.valueFormatter(valueFormatter)
.data(
{
value: xValue,
series: allData
@@ -13736,10 +14019,15 @@
interactiveLayer.dispatch.on("elementMouseout",function(e) {
stacked.clearHighlights();
});
+ /* Update `main' graph on brush update. */
+ focus.dispatch.on("onBrush", function(extent) {
+ onBrush(extent);
+ });
+
// Update chart from a state object passed to event handler
dispatch.on('changeState', function(e) {
if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) {
data.forEach(function(series,i) {
@@ -13755,10 +14043,38 @@
}
chart.update();
});
+ //============================================================
+ // Functions
+ //------------------------------------------------------------
+
+ function onBrush(extent) {
+ // Update Main (Focus)
+ var stackedWrap = g.select('.nv-focus .nv-stackedWrap')
+ .datum(
+ data.filter(function(d) { return !d.disabled; })
+ .map(function(d,i) {
+ return {
+ key: d.key,
+ area: d.area,
+ classed: d.classed,
+ values: d.values.filter(function(d,i) {
+ return stacked.x()(d,i) >= extent[0] && stacked.x()(d,i) <= extent[1];
+ }),
+ disableTooltip: d.disableTooltip
+ };
+ })
+ );
+ stackedWrap.transition().duration(duration).call(stacked);
+
+ // Update Main (Focus) Axes
+ updateXAxis();
+ updateYAxis();
+ }
+
});
renderWatch.renderEnd('stacked Area chart immediate');
return chart;
}
@@ -13774,24 +14090,26 @@
});
stacked.dispatch.on('elementMouseout.tooltip', function(evt) {
tooltip.hidden(true)
});
-
//============================================================
// Expose Public Variables
//------------------------------------------------------------
// expose chart's sub-components
chart.dispatch = dispatch;
chart.stacked = stacked;
chart.legend = legend;
chart.controls = controls;
chart.xAxis = xAxis;
+ chart.x2Axis = focus.xAxis;
chart.yAxis = yAxis;
+ chart.y2Axis = focus.yAxis;
chart.interactiveLayer = interactiveLayer;
chart.tooltip = tooltip;
+ chart.focus = focus;
chart.dispatch = dispatch;
chart.options = nv.utils.optionsFunc.bind(chart);
chart._options = Object.create({}, {
@@ -13806,18 +14124,27 @@
showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}},
showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}},
totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}},
+ focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
+ focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},
+ brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},
// options that require extra logic in the setter
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
margin.left = _.left !== undefined ? _.left : margin.left;
}},
+ focusMargin: {get: function(){return focus.margin}, set: function(_){
+ focus.margin.top = _.top !== undefined ? _.top : focus.margin.top;
+ focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;
+ focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;
+ focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;
+ }},
duration: {get: function(){return duration;}, set: function(_){
duration = _;
renderWatch.reset(duration);
stacked.duration(duration);
xAxis.duration(duration);
@@ -13825,11 +14152,20 @@
}},
color: {get: function(){return color;}, set: function(_){
color = nv.utils.getColor(_);
legend.color(color);
stacked.color(color);
+ focus.color(color);
}},
+ x: {get: function(){return stacked.x();}, set: function(_){
+ stacked.x(_);
+ focus.x(_);
+ }},
+ y: {get: function(){return stacked.y();}, set: function(_){
+ stacked.y(_);
+ focus.y(_);
+ }},
rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
rightAlignYAxis = _;
yAxis.orient( rightAlignYAxis ? 'right' : 'left');
}},
useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){
@@ -13843,10 +14179,16 @@
nv.utils.inheritOptions(chart, stacked);
nv.utils.initOptions(chart);
return chart;
};
+
+nv.models.stackedAreaWithFocusChart = function() {
+ return nv.models.stackedAreaChart()
+ .margin({ bottom: 30 })
+ .focusEnable( true );
+};
// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad
nv.models.sunburst = function() {
"use strict";
//============================================================
@@ -13903,10 +14245,16 @@
var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
var centerAngle = (((startAngle + endAngle) / 2) * (180 / Math.PI)) - 90;
return centerAngle;
}
+ function computeNodePercentage(d) {
+ var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));
+ var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
+ return (endAngle - startAngle) / (2 * Math.PI);
+ }
+
function labelThresholdMatched(d) {
var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));
var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
var size = endAngle - startAngle;
@@ -14052,11 +14400,13 @@
// Setup containers and skeleton of chart
var wrap = container.select('g.nvd3.nv-wrap.nv-sunburst');
if( !wrap[0][0] ) {
wrap = container.append('g')
.attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id)
- .attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
+ .attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');
+ } else {
+ wrap.attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');
}
container.on('click', function (d, i) {
dispatch.chartClick({
data: d,
@@ -14097,11 +14447,12 @@
.on("click", zoomClick)
.on('mouseover', function(d,i){
d3.select(this).classed('hover', true).style('opacity', 0.8);
dispatch.elementMouseover({
data: d,
- color: d3.select(this).style("fill")
+ color: d3.select(this).style("fill"),
+ percent: computeNodePercentage(d)
});
})
.on('mouseout', function(d,i){
d3.select(this).classed('hover', false).style('opacity', 1);
dispatch.elementMouseout({
@@ -14227,10 +14578,11 @@
var margin = {top: 30, right: 20, bottom: 20, left: 20}
, width = null
, height = null
, color = nv.utils.defaultColor()
+ , showTooltipPercent = false
, id = Math.round(Math.random() * 100000)
, defaultState = null
, noData = null
, duration = 250
, dispatch = d3.dispatch('stateChange', 'changeState','renderEnd');
@@ -14278,11 +14630,11 @@
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
- sunburst.width(availableWidth).height(availableHeight);
+ sunburst.width(availableWidth).height(availableHeight).margin(margin);
container.call(sunburst);
});
renderWatch.renderEnd('sunburstChart immediate');
return chart;
@@ -14294,12 +14646,17 @@
sunburst.dispatch.on('elementMouseover.tooltip', function(evt) {
evt.series = {
key: evt.data.name,
value: (evt.data.value || evt.data.size),
- color: evt.color
+ color: evt.color,
+ percent: evt.percent
};
+ if (!showTooltipPercent) {
+ delete evt.percent;
+ delete evt.series.percent;
+ }
tooltip.data(evt).hidden(false);
});
sunburst.dispatch.on('elementMouseout.tooltip', function(evt) {
tooltip.hidden(true);
@@ -14320,12 +14677,13 @@
chart.options = nv.utils.optionsFunc.bind(chart);
// use Object get/set functionality to map between vars and chart functions
chart._options = Object.create({}, {
// simple options, just get/set the necessary values
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
+ noData: {get: function(){return noData;}, set: function(_){noData=_;}},
+ defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
+ showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},
// options that require extra logic in the setter
color: {get: function(){return color;}, set: function(_){
color = _;
sunburst.color(color);
@@ -14338,15 +14696,16 @@
margin: {get: function(){return margin;}, set: function(_){
margin.top = _.top !== undefined ? _.top : margin.top;
margin.right = _.right !== undefined ? _.right : margin.right;
margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
margin.left = _.left !== undefined ? _.left : margin.left;
+ sunburst.margin(margin);
}}
});
nv.utils.inheritOptions(chart, sunburst);
nv.utils.initOptions(chart);
return chart;
};
-nv.version = "1.8.3";
-})();
\ No newline at end of file
+nv.version = "1.8.4";
+})();