novus-nvd3-rails 1.8.5 → 1.8.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/novus/nvd3/rails/version.rb +1 -1
- data/vendor/assets/javascripts/nv.d3.js +393 -146
- data/vendor/assets/stylesheets/nv.d3.css +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5a3b600d4ce921a4c4ef5efac45c6e33915acde
|
4
|
+
data.tar.gz: 19c327dad4f61916d35c02602a5ddec5604eb92d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '07694780ab62c0a622da40d5b0ca3b41f76b6e4f577d87d841529733c871746cca41a7a0ce0a286761150870e93786baf94e950eb2d49b0c0772ae5fcd5a8aa3'
|
7
|
+
data.tar.gz: 8684fb0dba933fd725c3f3ec4512e8f54f883eef0c8dc59d4ecdf5b80cb8cce98408c30d195f71018722ec71ca7bcb3d69df21c74bc790cedffdf885b1ff5bce
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* nvd3 version 1.8.
|
1
|
+
/* nvd3 version 1.8.6 (https://github.com/novus/nvd3) 2017-08-23 */
|
2
2
|
(function(){
|
3
3
|
|
4
4
|
// set up main nv object
|
@@ -221,9 +221,9 @@ nv.interactiveGuideline = function() {
|
|
221
221
|
}
|
222
222
|
|
223
223
|
function mouseHandler() {
|
224
|
-
var
|
225
|
-
var
|
226
|
-
|
224
|
+
var mouseX = d3.event.clientX - this.getBoundingClientRect().left;
|
225
|
+
var mouseY = d3.event.clientY - this.getBoundingClientRect().top;
|
226
|
+
|
227
227
|
var subtractMargin = true;
|
228
228
|
var mouseOutAnyReason = false;
|
229
229
|
if (isMSIE) {
|
@@ -556,7 +556,10 @@ nv.models.tooltip = function() {
|
|
556
556
|
;
|
557
557
|
|
558
558
|
// Format function for the tooltip values column.
|
559
|
-
|
559
|
+
// d is value,
|
560
|
+
// i is series index
|
561
|
+
// p is point containing the value
|
562
|
+
var valueFormatter = function(d, i, p) {
|
560
563
|
return d;
|
561
564
|
};
|
562
565
|
|
@@ -569,9 +572,10 @@ nv.models.tooltip = function() {
|
|
569
572
|
return d;
|
570
573
|
};
|
571
574
|
|
572
|
-
// By default, the tooltip model renders a beautiful table inside a DIV
|
573
|
-
// You can override this function if a custom tooltip is desired.
|
574
|
-
|
575
|
+
// By default, the tooltip model renders a beautiful table inside a DIV, returned as HTML
|
576
|
+
// You can override this function if a custom tooltip is desired. For instance, you could directly manipulate
|
577
|
+
// the DOM by accessing elem and returning false.
|
578
|
+
var contentGenerator = function(d, elem) {
|
575
579
|
if (d === null) {
|
576
580
|
return '';
|
577
581
|
}
|
@@ -612,7 +616,7 @@ nv.models.tooltip = function() {
|
|
612
616
|
|
613
617
|
trowEnter.append("td")
|
614
618
|
.classed("value",true)
|
615
|
-
.html(function(p, i) { return valueFormatter(p.value, i) });
|
619
|
+
.html(function(p, i) { return valueFormatter(p.value, i, p) });
|
616
620
|
|
617
621
|
trowEnter.filter(function (p,i) { return p.percent !== undefined }).append("td")
|
618
622
|
.classed("percent", true)
|
@@ -802,9 +806,9 @@ nv.models.tooltip = function() {
|
|
802
806
|
nv.dom.write(function () {
|
803
807
|
initTooltip();
|
804
808
|
// Generate data and set it into tooltip.
|
805
|
-
// Bonus - If you override contentGenerator and return
|
806
|
-
// React or Knockout to bind the data for your tooltip.
|
807
|
-
var newContent = contentGenerator(data);
|
809
|
+
// Bonus - If you override contentGenerator and return false, you can use something like
|
810
|
+
// Angular, React or Knockout to bind the data for your tooltip directly to the DOM.
|
811
|
+
var newContent = contentGenerator(data, tooltip.node());
|
808
812
|
if (newContent) {
|
809
813
|
tooltip.node().innerHTML = newContent;
|
810
814
|
}
|
@@ -1387,6 +1391,8 @@ Also use _d3options so we can track what we inherit for documentation and chaine
|
|
1387
1391
|
*/
|
1388
1392
|
nv.utils.inheritOptionsD3 = function(target, d3_source, oplist) {
|
1389
1393
|
target._d3options = oplist.concat(target._d3options || []);
|
1394
|
+
// Find unique d3 options (string) and update d3options
|
1395
|
+
target._d3options = (target._d3options || []).filter(function(item, i, ar){ return ar.indexOf(item) === i; });
|
1390
1396
|
oplist.unshift(d3_source);
|
1391
1397
|
oplist.unshift(target);
|
1392
1398
|
d3.rebind.apply(this, oplist);
|
@@ -1584,6 +1590,27 @@ nv.utils.arrayEquals = function (array1, array2) {
|
|
1584
1590
|
}
|
1585
1591
|
return true;
|
1586
1592
|
};
|
1593
|
+
|
1594
|
+
/*
|
1595
|
+
Check if a point within an arc
|
1596
|
+
*/
|
1597
|
+
nv.utils.pointIsInArc = function(pt, ptData, d3Arc) {
|
1598
|
+
// Center of the arc is assumed to be 0,0
|
1599
|
+
// (pt.x, pt.y) are assumed to be relative to the center
|
1600
|
+
var r1 = d3Arc.innerRadius()(ptData), // Note: Using the innerRadius
|
1601
|
+
r2 = d3Arc.outerRadius()(ptData),
|
1602
|
+
theta1 = d3Arc.startAngle()(ptData),
|
1603
|
+
theta2 = d3Arc.endAngle()(ptData);
|
1604
|
+
|
1605
|
+
var dist = pt.x * pt.x + pt.y * pt.y,
|
1606
|
+
angle = Math.atan2(pt.x, -pt.y); // Note: different coordinate system.
|
1607
|
+
|
1608
|
+
angle = (angle < 0) ? (angle + Math.PI * 2) : angle;
|
1609
|
+
|
1610
|
+
return (r1 * r1 <= dist) && (dist <= r2 * r2) &&
|
1611
|
+
(theta1 <= angle) && (angle <= theta2);
|
1612
|
+
};
|
1613
|
+
|
1587
1614
|
nv.models.axis = function() {
|
1588
1615
|
"use strict";
|
1589
1616
|
|
@@ -1608,6 +1635,7 @@ nv.models.axis = function() {
|
|
1608
1635
|
, fontSize = undefined
|
1609
1636
|
, duration = 250
|
1610
1637
|
, dispatch = d3.dispatch('renderEnd')
|
1638
|
+
, tickFormatMaxMin
|
1611
1639
|
;
|
1612
1640
|
axis
|
1613
1641
|
.scale(scale)
|
@@ -1692,7 +1720,8 @@ nv.models.axis = function() {
|
|
1692
1720
|
.attr('y', -axis.tickPadding())
|
1693
1721
|
.attr('text-anchor', 'middle')
|
1694
1722
|
.text(function(d,i) {
|
1695
|
-
var
|
1723
|
+
var formatter = tickFormatMaxMin || fmt;
|
1724
|
+
var v = formatter(d);
|
1696
1725
|
return ('' + v).match('NaN') ? '' : v;
|
1697
1726
|
});
|
1698
1727
|
axisMaxMin.watchTransition(renderWatch, 'min-max top')
|
@@ -1709,7 +1738,7 @@ nv.models.axis = function() {
|
|
1709
1738
|
var rotateLabelsRule = '';
|
1710
1739
|
if (rotateLabels%360) {
|
1711
1740
|
//Reset transform on ticks so textHeight can be calculated correctly
|
1712
|
-
xTicks.attr('transform', '');
|
1741
|
+
xTicks.attr('transform', '');
|
1713
1742
|
//Calculate the longest xTick width
|
1714
1743
|
xTicks.each(function(d,i){
|
1715
1744
|
var box = this.getBoundingClientRect();
|
@@ -1767,7 +1796,8 @@ nv.models.axis = function() {
|
|
1767
1796
|
.attr('transform', rotateLabelsRule)
|
1768
1797
|
.style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')
|
1769
1798
|
.text(function(d,i) {
|
1770
|
-
var
|
1799
|
+
var formatter = tickFormatMaxMin || fmt;
|
1800
|
+
var v = formatter(d);
|
1771
1801
|
return ('' + v).match('NaN') ? '' : v;
|
1772
1802
|
});
|
1773
1803
|
axisMaxMin.watchTransition(renderWatch, 'min-max bottom')
|
@@ -1802,7 +1832,8 @@ nv.models.axis = function() {
|
|
1802
1832
|
.attr('x', axis.tickPadding())
|
1803
1833
|
.style('text-anchor', 'start')
|
1804
1834
|
.text(function(d, i) {
|
1805
|
-
var
|
1835
|
+
var formatter = tickFormatMaxMin || fmt;
|
1836
|
+
var v = formatter(d);
|
1806
1837
|
return ('' + v).match('NaN') ? '' : v;
|
1807
1838
|
});
|
1808
1839
|
axisMaxMin.watchTransition(renderWatch, 'min-max right')
|
@@ -1846,7 +1877,8 @@ nv.models.axis = function() {
|
|
1846
1877
|
.attr('x', -axis.tickPadding())
|
1847
1878
|
.attr('text-anchor', 'end')
|
1848
1879
|
.text(function(d,i) {
|
1849
|
-
var
|
1880
|
+
var formatter = tickFormatMaxMin || fmt;
|
1881
|
+
var v = formatter(d);
|
1850
1882
|
return ('' + v).match('NaN') ? '' : v;
|
1851
1883
|
});
|
1852
1884
|
axisMaxMin.watchTransition(renderWatch, 'min-max right')
|
@@ -1917,9 +1949,9 @@ nv.models.axis = function() {
|
|
1917
1949
|
and the arithmetic trick below solves that.
|
1918
1950
|
*/
|
1919
1951
|
return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined)
|
1920
|
-
})
|
1952
|
+
})
|
1921
1953
|
.classed('zero', true);
|
1922
|
-
|
1954
|
+
|
1923
1955
|
//store old scales for use in transitions on update
|
1924
1956
|
scale0 = scale.copy();
|
1925
1957
|
|
@@ -1950,6 +1982,7 @@ nv.models.axis = function() {
|
|
1950
1982
|
ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}},
|
1951
1983
|
width: {get: function(){return width;}, set: function(_){width=_;}},
|
1952
1984
|
fontSize: {get: function(){return fontSize;}, set: function(_){fontSize=_;}},
|
1985
|
+
tickFormatMaxMin: {get: function(){return tickFormatMaxMin;}, set: function(_){tickFormatMaxMin=_;}},
|
1953
1986
|
|
1954
1987
|
// options that require extra logic in the setter
|
1955
1988
|
margin: {get: function(){return margin;}, set: function(_){
|
@@ -3350,6 +3383,7 @@ nv.models.cumulativeLineChart = function() {
|
|
3350
3383
|
var dx = d3.scale.linear()
|
3351
3384
|
, index = {i: 0, x: 0}
|
3352
3385
|
, renderWatch = nv.utils.renderWatch(dispatch, duration)
|
3386
|
+
, currentYDomain
|
3353
3387
|
;
|
3354
3388
|
|
3355
3389
|
var stateGetter = function(data) {
|
@@ -3454,30 +3488,6 @@ nv.models.cumulativeLineChart = function() {
|
|
3454
3488
|
x = lines.xScale();
|
3455
3489
|
y = lines.yScale();
|
3456
3490
|
|
3457
|
-
if (!rescaleY) {
|
3458
|
-
var seriesDomains = data
|
3459
|
-
.filter(function(series) { return !series.disabled })
|
3460
|
-
.map(function(series,i) {
|
3461
|
-
var initialDomain = d3.extent(series.values, lines.y());
|
3462
|
-
|
3463
|
-
//account for series being disabled when losing 95% or more
|
3464
|
-
if (initialDomain[0] < -.95) initialDomain[0] = -.95;
|
3465
|
-
|
3466
|
-
return [
|
3467
|
-
(initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
|
3468
|
-
(initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
|
3469
|
-
];
|
3470
|
-
});
|
3471
|
-
|
3472
|
-
var completeDomain = [
|
3473
|
-
d3.min(seriesDomains, function(d) { return d[0] }),
|
3474
|
-
d3.max(seriesDomains, function(d) { return d[1] })
|
3475
|
-
];
|
3476
|
-
|
3477
|
-
lines.yDomain(completeDomain);
|
3478
|
-
} else {
|
3479
|
-
lines.yDomain(null);
|
3480
|
-
}
|
3481
3491
|
|
3482
3492
|
dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length
|
3483
3493
|
.range([0, availableWidth])
|
@@ -3485,6 +3495,18 @@ nv.models.cumulativeLineChart = function() {
|
|
3485
3495
|
|
3486
3496
|
var data = indexify(index.i, data);
|
3487
3497
|
|
3498
|
+
// initialize the starting yDomain for the not-rescale case after indexify (to have calculated point.display)
|
3499
|
+
if (typeof(currentYDomain) === "undefined") {
|
3500
|
+
currentYDomain = getCurrentYDomain(data);
|
3501
|
+
}
|
3502
|
+
|
3503
|
+
if (!rescaleY) {
|
3504
|
+
lines.yDomain(currentYDomain);
|
3505
|
+
lines.clipEdge(true);
|
3506
|
+
} else {
|
3507
|
+
lines.yDomain(null);
|
3508
|
+
}
|
3509
|
+
|
3488
3510
|
// Setup containers and skeleton of chart
|
3489
3511
|
var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";
|
3490
3512
|
var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
|
@@ -3547,7 +3569,7 @@ nv.models.cumulativeLineChart = function() {
|
|
3547
3569
|
.attr("transform", "translate(" + availableWidth + ",0)");
|
3548
3570
|
}
|
3549
3571
|
|
3550
|
-
// Show error if
|
3572
|
+
// Show error if index point value is 0 (division by zero avoided)
|
3551
3573
|
var tempDisabled = data.filter(function(d) { return d.tempDisabled });
|
3552
3574
|
|
3553
3575
|
wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
|
@@ -3717,8 +3739,10 @@ nv.models.cumulativeLineChart = function() {
|
|
3717
3739
|
controls.dispatch.on('legendClick', function(d,i) {
|
3718
3740
|
d.disabled = !d.disabled;
|
3719
3741
|
rescaleY = !d.disabled;
|
3720
|
-
|
3721
3742
|
state.rescaleY = rescaleY;
|
3743
|
+
if (!rescaleY) {
|
3744
|
+
currentYDomain = getCurrentYDomain(data); // rescale is turned off, so set the currentYDomain
|
3745
|
+
}
|
3722
3746
|
dispatch.stateChange(state);
|
3723
3747
|
chart.update();
|
3724
3748
|
});
|
@@ -3737,7 +3761,7 @@ nv.models.cumulativeLineChart = function() {
|
|
3737
3761
|
data
|
3738
3762
|
.filter(function(series, i) {
|
3739
3763
|
series.seriesIndex = i;
|
3740
|
-
return !series.disabled;
|
3764
|
+
return !(series.disabled || series.tempDisabled);
|
3741
3765
|
})
|
3742
3766
|
.forEach(function(series,i) {
|
3743
3767
|
pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
|
@@ -3852,10 +3876,8 @@ nv.models.cumulativeLineChart = function() {
|
|
3852
3876
|
}
|
3853
3877
|
var v = indexifyYGetter(indexValue, idx);
|
3854
3878
|
|
3855
|
-
//
|
3856
|
-
if (v <
|
3857
|
-
//if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
|
3858
|
-
|
3879
|
+
// avoid divide by zero
|
3880
|
+
if (Math.abs(v) < 0.00001 && !noErrorCheck) {
|
3859
3881
|
line.tempDisabled = true;
|
3860
3882
|
return line;
|
3861
3883
|
}
|
@@ -3863,7 +3885,7 @@ nv.models.cumulativeLineChart = function() {
|
|
3863
3885
|
line.tempDisabled = false;
|
3864
3886
|
|
3865
3887
|
line.values = line.values.map(function(point, pointIndex) {
|
3866
|
-
point.display = {'y': (indexifyYGetter(point, pointIndex) - v) /
|
3888
|
+
point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / v };
|
3867
3889
|
return point;
|
3868
3890
|
});
|
3869
3891
|
|
@@ -3871,6 +3893,19 @@ nv.models.cumulativeLineChart = function() {
|
|
3871
3893
|
})
|
3872
3894
|
}
|
3873
3895
|
|
3896
|
+
function getCurrentYDomain(data) {
|
3897
|
+
var seriesDomains = data
|
3898
|
+
.filter(function(series) { return !(series.disabled || series.tempDisabled)})
|
3899
|
+
.map(function(series,i) {
|
3900
|
+
return d3.extent(series.values, function (d) { return d.display.y });
|
3901
|
+
});
|
3902
|
+
|
3903
|
+
return [
|
3904
|
+
d3.min(seriesDomains, function(d) { return d[0] }),
|
3905
|
+
d3.max(seriesDomains, function(d) { return d[1] })
|
3906
|
+
];
|
3907
|
+
}
|
3908
|
+
|
3874
3909
|
//============================================================
|
3875
3910
|
// Expose Public Variables
|
3876
3911
|
//------------------------------------------------------------
|
@@ -3892,7 +3927,6 @@ nv.models.cumulativeLineChart = function() {
|
|
3892
3927
|
// simple options, just get/set the necessary values
|
3893
3928
|
width: {get: function(){return width;}, set: function(_){width=_;}},
|
3894
3929
|
height: {get: function(){return height;}, set: function(_){height=_;}},
|
3895
|
-
rescaleY: {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}},
|
3896
3930
|
showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
|
3897
3931
|
showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
|
3898
3932
|
average: {get: function(){return average;}, set: function(_){average=_;}},
|
@@ -3903,6 +3937,10 @@ nv.models.cumulativeLineChart = function() {
|
|
3903
3937
|
noErrorCheck: {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}},
|
3904
3938
|
|
3905
3939
|
// options that require extra logic in the setter
|
3940
|
+
rescaleY: {get: function(){return rescaleY;}, set: function(_){
|
3941
|
+
rescaleY = _;
|
3942
|
+
chart.state.rescaleY = _; // also update state
|
3943
|
+
}},
|
3906
3944
|
margin: {get: function(){return margin;}, set: function(_){
|
3907
3945
|
if (_.top !== undefined) {
|
3908
3946
|
margin.top = _.top;
|
@@ -4958,6 +4996,8 @@ nv.models.forceDirectedGraph = function() {
|
|
4958
4996
|
// These functions allow to add extra attributes to ndes and links
|
4959
4997
|
,nodeExtras = function(nodes) { /* Do nothing */ }
|
4960
4998
|
,linkExtras = function(links) { /* Do nothing */ }
|
4999
|
+
, getX=d3.functor(0.0)
|
5000
|
+
, getY=d3.functor(0.0)
|
4961
5001
|
;
|
4962
5002
|
|
4963
5003
|
|
@@ -6126,6 +6166,7 @@ nv.models.legend = function() {
|
|
6126
6166
|
, padding = 32 //define how much space between legend items. - recommend 32 for furious version
|
6127
6167
|
, rightAlign = true
|
6128
6168
|
, updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
|
6169
|
+
, enableDoubleClick = true //If true, legend will enable double click handling
|
6129
6170
|
, radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)
|
6130
6171
|
, expanded = false
|
6131
6172
|
, dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
|
@@ -6258,22 +6299,26 @@ nv.models.legend = function() {
|
|
6258
6299
|
}
|
6259
6300
|
})
|
6260
6301
|
.on('dblclick', function(d,i) {
|
6261
|
-
if(
|
6262
|
-
|
6263
|
-
|
6264
|
-
|
6265
|
-
|
6266
|
-
|
6267
|
-
|
6268
|
-
|
6269
|
-
|
6270
|
-
|
6271
|
-
|
6272
|
-
|
6273
|
-
|
6274
|
-
|
6275
|
-
|
6276
|
-
|
6302
|
+
if (enableDoubleClick) {
|
6303
|
+
if (vers == 'furious' && expanded) return;
|
6304
|
+
dispatch.legendDblclick(d, i);
|
6305
|
+
if (updateState) {
|
6306
|
+
// make sure we re-get data in case it was modified
|
6307
|
+
var data = series.data();
|
6308
|
+
//the default behavior of NVD3 legends, when double clicking one,
|
6309
|
+
// is to set all other series' to false, and make the double clicked series enabled.
|
6310
|
+
data.forEach(function (series) {
|
6311
|
+
series.disabled = true;
|
6312
|
+
if (vers == 'furious') series.userDisabled = series.disabled;
|
6313
|
+
});
|
6314
|
+
d.disabled = false;
|
6315
|
+
if (vers == 'furious') d.userDisabled = d.disabled;
|
6316
|
+
dispatch.stateChange({
|
6317
|
+
disabled: data.map(function (d) {
|
6318
|
+
return !!d.disabled
|
6319
|
+
})
|
6320
|
+
});
|
6321
|
+
}
|
6277
6322
|
}
|
6278
6323
|
});
|
6279
6324
|
|
@@ -6472,6 +6517,7 @@ nv.models.legend = function() {
|
|
6472
6517
|
rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
|
6473
6518
|
padding: {get: function(){return padding;}, set: function(_){padding=_;}},
|
6474
6519
|
updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
|
6520
|
+
enableDoubleClick: {get: function(){return enableDoubleClick;}, set: function(_){enableDoubleClick=_;}},
|
6475
6521
|
radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
|
6476
6522
|
expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
|
6477
6523
|
vers: {get: function(){return vers;}, set: function(_){vers=_;}},
|
@@ -6754,7 +6800,7 @@ nv.models.lineChart = function() {
|
|
6754
6800
|
, state = nv.utils.state()
|
6755
6801
|
, defaultState = null
|
6756
6802
|
, noData = null
|
6757
|
-
, dispatch = d3.dispatch('
|
6803
|
+
, dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd')
|
6758
6804
|
, duration = 250
|
6759
6805
|
;
|
6760
6806
|
|
@@ -6883,8 +6929,10 @@ nv.models.lineChart = function() {
|
|
6883
6929
|
.call(legend);
|
6884
6930
|
|
6885
6931
|
if (legendPosition === 'bottom') {
|
6886
|
-
|
6887
|
-
|
6932
|
+
margin.bottom = xAxis.height() + legend.height();
|
6933
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
6934
|
+
g.select('.nv-legendWrap')
|
6935
|
+
.attr('transform', 'translate(0,' + (availableHeight + xAxis.height()) +')');
|
6888
6936
|
} else if (legendPosition === 'top') {
|
6889
6937
|
if (!marginTop && legend.height() !== margin.top) {
|
6890
6938
|
margin.top = legend.height();
|
@@ -6973,18 +7021,18 @@ nv.models.lineChart = function() {
|
|
6973
7021
|
//============================================================
|
6974
7022
|
// Update Focus
|
6975
7023
|
//============================================================
|
6976
|
-
if(!focusEnable) {
|
7024
|
+
if (!focusEnable && focus.brush.extent() === null) {
|
6977
7025
|
linesWrap.call(lines);
|
6978
7026
|
updateXAxis();
|
6979
7027
|
updateYAxis();
|
6980
7028
|
} else {
|
6981
7029
|
focus.width(availableWidth);
|
6982
7030
|
g.select('.nv-focusWrap')
|
7031
|
+
.style('display', focusEnable ? 'initial' : 'none')
|
6983
7032
|
.attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')
|
6984
|
-
.datum(data.filter(function(d) { return !d.disabled; }))
|
6985
7033
|
.call(focus);
|
6986
7034
|
var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();
|
6987
|
-
if(extent !== null){
|
7035
|
+
if (extent !== null) {
|
6988
7036
|
onBrush(extent);
|
6989
7037
|
}
|
6990
7038
|
}
|
@@ -7008,7 +7056,7 @@ nv.models.lineChart = function() {
|
|
7008
7056
|
return !series.disabled && !series.disableTooltip;
|
7009
7057
|
})
|
7010
7058
|
.forEach(function(series,i) {
|
7011
|
-
var extent =
|
7059
|
+
var extent = focus.brush.extent() !== null ? (focus.brush.empty() ? focus.xScale().domain() : focus.brush.extent()) : x.domain();
|
7012
7060
|
var currentValues = series.values.filter(function(d,i) {
|
7013
7061
|
// Checks if the x point is between the extents, handling case where extent[0] is greater than extent[1]
|
7014
7062
|
// (e.g. x domain is manually set to reverse the x-axis)
|
@@ -8176,44 +8224,49 @@ nv.models.multiBar = function() {
|
|
8176
8224
|
bars
|
8177
8225
|
.style('fill', function(d,i,j){ return color(d, j, i); })
|
8178
8226
|
.style('stroke', function(d,i,j){ return color(d, j, i); })
|
8179
|
-
.on('mouseover', function(d,i) {
|
8227
|
+
.on('mouseover', function(d,i,j) {
|
8180
8228
|
d3.select(this).classed('hover', true);
|
8181
8229
|
dispatch.elementMouseover({
|
8182
8230
|
data: d,
|
8183
8231
|
index: i,
|
8232
|
+
series: data[j],
|
8184
8233
|
color: d3.select(this).style("fill")
|
8185
8234
|
});
|
8186
8235
|
})
|
8187
|
-
.on('mouseout', function(d,i) {
|
8236
|
+
.on('mouseout', function(d,i,j) {
|
8188
8237
|
d3.select(this).classed('hover', false);
|
8189
8238
|
dispatch.elementMouseout({
|
8190
8239
|
data: d,
|
8191
8240
|
index: i,
|
8241
|
+
series: data[j],
|
8192
8242
|
color: d3.select(this).style("fill")
|
8193
8243
|
});
|
8194
8244
|
})
|
8195
|
-
.on('mousemove', function(d,i) {
|
8245
|
+
.on('mousemove', function(d,i,j) {
|
8196
8246
|
dispatch.elementMousemove({
|
8197
8247
|
data: d,
|
8198
8248
|
index: i,
|
8249
|
+
series: data[j],
|
8199
8250
|
color: d3.select(this).style("fill")
|
8200
8251
|
});
|
8201
8252
|
})
|
8202
|
-
.on('click', function(d,i) {
|
8253
|
+
.on('click', function(d,i,j) {
|
8203
8254
|
var element = this;
|
8204
8255
|
dispatch.elementClick({
|
8205
8256
|
data: d,
|
8206
8257
|
index: i,
|
8258
|
+
series: data[j],
|
8207
8259
|
color: d3.select(this).style("fill"),
|
8208
8260
|
event: d3.event,
|
8209
8261
|
element: element
|
8210
8262
|
});
|
8211
8263
|
d3.event.stopPropagation();
|
8212
8264
|
})
|
8213
|
-
.on('dblclick', function(d,i) {
|
8265
|
+
.on('dblclick', function(d,i,j) {
|
8214
8266
|
dispatch.elementDblClick({
|
8215
8267
|
data: d,
|
8216
8268
|
index: i,
|
8269
|
+
series: data[j],
|
8217
8270
|
color: d3.select(this).style("fill")
|
8218
8271
|
});
|
8219
8272
|
d3.event.stopPropagation();
|
@@ -8397,6 +8450,7 @@ nv.models.multiBarChart = function() {
|
|
8397
8450
|
, showControls = true
|
8398
8451
|
, controlLabels = {}
|
8399
8452
|
, showLegend = true
|
8453
|
+
, legendPosition = null
|
8400
8454
|
, showXAxis = true
|
8401
8455
|
, showYAxis = true
|
8402
8456
|
, rightAlignYAxis = false
|
@@ -8562,19 +8616,32 @@ nv.models.multiBarChart = function() {
|
|
8562
8616
|
if (!showLegend) {
|
8563
8617
|
g.select('.nv-legendWrap').selectAll('*').remove();
|
8564
8618
|
} else {
|
8565
|
-
|
8619
|
+
if (legendPosition === 'bottom') {
|
8620
|
+
legend.width(availableWidth - margin.right);
|
8566
8621
|
|
8567
|
-
|
8568
|
-
|
8569
|
-
|
8622
|
+
g.select('.nv-legendWrap')
|
8623
|
+
.datum(data)
|
8624
|
+
.call(legend);
|
8570
8625
|
|
8571
|
-
|
8572
|
-
|
8573
|
-
|
8574
|
-
|
8626
|
+
margin.bottom = xAxis.height() + legend.height();
|
8627
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
8628
|
+
g.select('.nv-legendWrap')
|
8629
|
+
.attr('transform', 'translate(0,' + (availableHeight + xAxis.height()) +')');
|
8630
|
+
} else {
|
8631
|
+
legend.width(availableWidth - controlWidth());
|
8575
8632
|
|
8576
|
-
|
8577
|
-
|
8633
|
+
g.select('.nv-legendWrap')
|
8634
|
+
.datum(data)
|
8635
|
+
.call(legend);
|
8636
|
+
|
8637
|
+
if (!marginTop && legend.height() !== margin.top) {
|
8638
|
+
margin.top = legend.height();
|
8639
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
8640
|
+
}
|
8641
|
+
|
8642
|
+
g.select('.nv-legendWrap')
|
8643
|
+
.attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
|
8644
|
+
}
|
8578
8645
|
}
|
8579
8646
|
|
8580
8647
|
// Controls
|
@@ -8835,6 +8902,7 @@ nv.models.multiBarChart = function() {
|
|
8835
8902
|
width: {get: function(){return width;}, set: function(_){width=_;}},
|
8836
8903
|
height: {get: function(){return height;}, set: function(_){height=_;}},
|
8837
8904
|
showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
|
8905
|
+
legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
|
8838
8906
|
showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
|
8839
8907
|
controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
|
8840
8908
|
showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
|
@@ -9095,13 +9163,13 @@ nv.models.multiBarHorizontal = function() {
|
|
9095
9163
|
var xerr = getYerr(d,i)
|
9096
9164
|
, mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2);
|
9097
9165
|
xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)];
|
9098
|
-
xerr = xerr.map(function(e) { return y(e) - y(0); });
|
9166
|
+
xerr = xerr.map(function(e) { return y(e + ((getY(d,i) < 0) ? 0 : getY(d,i))) - y(0); });
|
9099
9167
|
var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]];
|
9100
9168
|
return a.map(function (path) { return path.join(',') }).join(' ');
|
9101
9169
|
})
|
9102
9170
|
.attr('transform', function(d,i) {
|
9103
9171
|
var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2);
|
9104
|
-
return 'translate(
|
9172
|
+
return 'translate(0, ' + mid + ')';
|
9105
9173
|
});
|
9106
9174
|
}
|
9107
9175
|
|
@@ -9269,8 +9337,10 @@ nv.models.multiBarHorizontalChart = function() {
|
|
9269
9337
|
, height = null
|
9270
9338
|
, color = nv.utils.defaultColor()
|
9271
9339
|
, showControls = true
|
9340
|
+
, controlsPosition = 'top'
|
9272
9341
|
, controlLabels = {}
|
9273
9342
|
, showLegend = true
|
9343
|
+
, legendPosition = 'top'
|
9274
9344
|
, showXAxis = true
|
9275
9345
|
, showYAxis = true
|
9276
9346
|
, stacked = false
|
@@ -9407,14 +9477,21 @@ nv.models.multiBarHorizontalChart = function() {
|
|
9407
9477
|
g.select('.nv-legendWrap')
|
9408
9478
|
.datum(data)
|
9409
9479
|
.call(legend);
|
9480
|
+
if (legendPosition === 'bottom') {
|
9481
|
+
margin.bottom = xAxis.height() + legend.height();
|
9482
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
9483
|
+
g.select('.nv-legendWrap')
|
9484
|
+
.attr('transform', 'translate(' + controlWidth() + ',' + (availableHeight + xAxis.height()) +')');
|
9485
|
+
} else if (legendPosition === 'top') {
|
9410
9486
|
|
9411
|
-
|
9412
|
-
|
9413
|
-
|
9414
|
-
|
9487
|
+
if (!marginTop && legend.height() !== margin.top) {
|
9488
|
+
margin.top = legend.height();
|
9489
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
9490
|
+
}
|
9415
9491
|
|
9416
|
-
|
9417
|
-
|
9492
|
+
g.select('.nv-legendWrap')
|
9493
|
+
.attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
|
9494
|
+
}
|
9418
9495
|
}
|
9419
9496
|
|
9420
9497
|
// Controls
|
@@ -9427,10 +9504,21 @@ nv.models.multiBarHorizontalChart = function() {
|
|
9427
9504
|
];
|
9428
9505
|
|
9429
9506
|
controls.width(controlWidth()).color(['#444', '#444', '#444']);
|
9430
|
-
|
9431
|
-
|
9432
|
-
|
9433
|
-
|
9507
|
+
|
9508
|
+
if (controlsPosition === 'bottom') {
|
9509
|
+
margin.bottom = xAxis.height() + legend.height();
|
9510
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
9511
|
+
g.select('.nv-controlsWrap')
|
9512
|
+
.datum(controlsData)
|
9513
|
+
.attr('transform', 'translate(0,' + (availableHeight + xAxis.height()) +')')
|
9514
|
+
.call(controls);
|
9515
|
+
|
9516
|
+
} else if (controlsPosition === 'top') {
|
9517
|
+
g.select('.nv-controlsWrap')
|
9518
|
+
.datum(controlsData)
|
9519
|
+
.attr('transform', 'translate(0,' + (-margin.top) +')')
|
9520
|
+
.call(controls);
|
9521
|
+
}
|
9434
9522
|
}
|
9435
9523
|
|
9436
9524
|
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
@@ -9587,6 +9675,8 @@ nv.models.multiBarHorizontalChart = function() {
|
|
9587
9675
|
width: {get: function(){return width;}, set: function(_){width=_;}},
|
9588
9676
|
height: {get: function(){return height;}, set: function(_){height=_;}},
|
9589
9677
|
showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
|
9678
|
+
legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
|
9679
|
+
controlsPosition: {get: function(){return controlsPosition;}, set: function(_){controlsPosition=_;}},
|
9590
9680
|
showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}},
|
9591
9681
|
controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}},
|
9592
9682
|
showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
|
@@ -9834,17 +9924,36 @@ nv.models.multiChart = function() {
|
|
9834
9924
|
var stack2Wrap = g.select('.stack2Wrap')
|
9835
9925
|
.datum(dataStack2.filter(function(d){return !d.disabled}));
|
9836
9926
|
|
9837
|
-
var
|
9838
|
-
|
9839
|
-
|
9840
|
-
|
9841
|
-
|
9842
|
-
|
9843
|
-
|
9844
|
-
|
9927
|
+
var extraValue1BarStacked = [];
|
9928
|
+
if (bars1.stacked() && dataBars1.length) {
|
9929
|
+
var extraValue1BarStacked = dataBars1.filter(function(d){return !d.disabled}).map(function(a){return a.values});
|
9930
|
+
|
9931
|
+
if (extraValue1BarStacked.length > 0)
|
9932
|
+
extraValue1BarStacked = extraValue1BarStacked.reduce(function(a,b){
|
9933
|
+
return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
|
9934
|
+
});
|
9935
|
+
}
|
9936
|
+
if (dataBars1.length) {
|
9937
|
+
extraValue1BarStacked.push({x:0, y:0});
|
9938
|
+
}
|
9939
|
+
|
9940
|
+
var extraValue2BarStacked = [];
|
9941
|
+
if (bars2.stacked() && dataBars2.length) {
|
9942
|
+
var extraValue2BarStacked = dataBars2.filter(function(d){return !d.disabled}).map(function(a){return a.values});
|
9943
|
+
|
9944
|
+
if (extraValue2BarStacked.length > 0)
|
9945
|
+
extraValue2BarStacked = extraValue2BarStacked.reduce(function(a,b){
|
9946
|
+
return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})
|
9947
|
+
});
|
9948
|
+
}
|
9949
|
+
if (dataBars2.length) {
|
9950
|
+
extraValue2BarStacked.push({x:0, y:0});
|
9951
|
+
}
|
9952
|
+
|
9953
|
+
yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1BarStacked), function(d) { return d.y } ))
|
9845
9954
|
.range([0, availableHeight]);
|
9846
9955
|
|
9847
|
-
yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(
|
9956
|
+
yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2BarStacked), function(d) { return d.y } ))
|
9848
9957
|
.range([0, availableHeight]);
|
9849
9958
|
|
9850
9959
|
lines1.yDomain(yScale1.domain());
|
@@ -9920,7 +10029,7 @@ nv.models.multiChart = function() {
|
|
9920
10029
|
//------------------------------------------------------------
|
9921
10030
|
|
9922
10031
|
function mouseover_line(evt) {
|
9923
|
-
var yaxis =
|
10032
|
+
var yaxis = evt.series.yAxis === 2 ? yAxis2 : yAxis1;
|
9924
10033
|
evt.value = evt.point.x;
|
9925
10034
|
evt.series = {
|
9926
10035
|
value: evt.point.y,
|
@@ -9940,7 +10049,7 @@ nv.models.multiChart = function() {
|
|
9940
10049
|
}
|
9941
10050
|
|
9942
10051
|
function mouseover_scatter(evt) {
|
9943
|
-
var yaxis =
|
10052
|
+
var yaxis = evt.series.yAxis === 2 ? yAxis2 : yAxis1;
|
9944
10053
|
evt.value = evt.point.x;
|
9945
10054
|
evt.series = {
|
9946
10055
|
value: evt.point.y,
|
@@ -9960,7 +10069,7 @@ nv.models.multiChart = function() {
|
|
9960
10069
|
}
|
9961
10070
|
|
9962
10071
|
function mouseover_stack(evt) {
|
9963
|
-
var yaxis =
|
10072
|
+
var yaxis = evt.series.yAxis === 2 ? yAxis2 : yAxis1;
|
9964
10073
|
evt.point['x'] = stack1.x()(evt.point);
|
9965
10074
|
evt.point['y'] = stack1.y()(evt.point);
|
9966
10075
|
tooltip
|
@@ -9976,7 +10085,7 @@ nv.models.multiChart = function() {
|
|
9976
10085
|
}
|
9977
10086
|
|
9978
10087
|
function mouseover_bar(evt) {
|
9979
|
-
var yaxis =
|
10088
|
+
var yaxis = evt.series.yAxis === 2 ? yAxis2 : yAxis1;
|
9980
10089
|
|
9981
10090
|
evt.value = bars1.x()(evt.data);
|
9982
10091
|
evt['series'] = {
|
@@ -11266,6 +11375,7 @@ nv.models.pie = function() {
|
|
11266
11375
|
, labelsOutside = false
|
11267
11376
|
, labelType = "key"
|
11268
11377
|
, labelThreshold = .02 //if slice percentage is under this, don't show label
|
11378
|
+
, hideOverlapLabels = false //Hide labels that don't fit in slice
|
11269
11379
|
, donut = false
|
11270
11380
|
, title = false
|
11271
11381
|
, growOnHover = true
|
@@ -11302,7 +11412,7 @@ nv.models.pie = function() {
|
|
11302
11412
|
|
11303
11413
|
container = d3.select(this)
|
11304
11414
|
if (arcsRadius.length === 0) {
|
11305
|
-
var outer = radius - radius /
|
11415
|
+
var outer = radius - radius / 10;
|
11306
11416
|
var inner = donutRatio * radius;
|
11307
11417
|
for (var i = 0; i < data[0].length; i++) {
|
11308
11418
|
arcsRadiusOuter.push(outer);
|
@@ -11310,9 +11420,9 @@ nv.models.pie = function() {
|
|
11310
11420
|
}
|
11311
11421
|
} else {
|
11312
11422
|
if(growOnHover){
|
11313
|
-
arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer /
|
11314
|
-
arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner /
|
11315
|
-
donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner /
|
11423
|
+
arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 10) * radius; });
|
11424
|
+
arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 10) * radius; });
|
11425
|
+
donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 10); }));
|
11316
11426
|
} else {
|
11317
11427
|
arcsRadiusOuter = arcsRadius.map(function (d) { return d.outer * radius; });
|
11318
11428
|
arcsRadiusInner = arcsRadius.map(function (d) { return d.inner * radius; });
|
@@ -11587,6 +11697,44 @@ nv.models.pie = function() {
|
|
11587
11697
|
return label;
|
11588
11698
|
})
|
11589
11699
|
;
|
11700
|
+
|
11701
|
+
if (hideOverlapLabels) {
|
11702
|
+
pieLabels
|
11703
|
+
.each(function (d, i) {
|
11704
|
+
if (!this.getBBox) return;
|
11705
|
+
var bb = this.getBBox(),
|
11706
|
+
center = labelsArc[i].centroid(d);
|
11707
|
+
var topLeft = {
|
11708
|
+
x : center[0] + bb.x,
|
11709
|
+
y : center[1] + bb.y
|
11710
|
+
};
|
11711
|
+
|
11712
|
+
var topRight = {
|
11713
|
+
x : topLeft.x + bb.width,
|
11714
|
+
y : topLeft.y
|
11715
|
+
};
|
11716
|
+
|
11717
|
+
var bottomLeft = {
|
11718
|
+
x : topLeft.x,
|
11719
|
+
y : topLeft.y + bb.height
|
11720
|
+
};
|
11721
|
+
|
11722
|
+
var bottomRight = {
|
11723
|
+
x : topLeft.x + bb.width,
|
11724
|
+
y : topLeft.y + bb.height
|
11725
|
+
};
|
11726
|
+
|
11727
|
+
d.visible = nv.utils.pointIsInArc(topLeft, d, arc) &&
|
11728
|
+
nv.utils.pointIsInArc(topRight, d, arc) &&
|
11729
|
+
nv.utils.pointIsInArc(bottomLeft, d, arc) &&
|
11730
|
+
nv.utils.pointIsInArc(bottomRight, d, arc);
|
11731
|
+
})
|
11732
|
+
.style('display', function (d) {
|
11733
|
+
return d.visible ? null : 'none';
|
11734
|
+
})
|
11735
|
+
;
|
11736
|
+
}
|
11737
|
+
|
11590
11738
|
}
|
11591
11739
|
|
11592
11740
|
|
@@ -11628,6 +11776,7 @@ nv.models.pie = function() {
|
|
11628
11776
|
title: {get: function(){return title;}, set: function(_){title=_;}},
|
11629
11777
|
titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}},
|
11630
11778
|
labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}},
|
11779
|
+
hideOverlapLabels: {get: function(){return hideOverlapLabels;}, set: function(_){hideOverlapLabels=_;}},
|
11631
11780
|
valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
|
11632
11781
|
x: {get: function(){return getX;}, set: function(_){getX=_;}},
|
11633
11782
|
id: {get: function(){return id;}, set: function(_){id=_;}},
|
@@ -11823,6 +11972,16 @@ nv.models.pieChart = function() {
|
|
11823
11972
|
.datum(data)
|
11824
11973
|
.call(legend)
|
11825
11974
|
.attr('transform', 'translate(' + (availableWidth) +',0)');
|
11975
|
+
} else if (legendPosition === "bottom") {
|
11976
|
+
legend.width( availableWidth ).key(pie.x());
|
11977
|
+
wrap.select('.nv-legendWrap')
|
11978
|
+
.datum(data)
|
11979
|
+
.call(legend);
|
11980
|
+
|
11981
|
+
margin.bottom = legend.height();
|
11982
|
+
availableHeight = nv.utils.availableHeight(height, container, margin);
|
11983
|
+
wrap.select('.nv-legendWrap')
|
11984
|
+
.attr('transform', 'translate(0,' + availableHeight +')');
|
11826
11985
|
}
|
11827
11986
|
}
|
11828
11987
|
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
@@ -12548,6 +12707,7 @@ nv.models.scatter = function() {
|
|
12548
12707
|
//------------------------------------------------------------
|
12549
12708
|
|
12550
12709
|
var x0, y0, z0 // used to store previous scales
|
12710
|
+
, xDom, yDom // used to store previous domains
|
12551
12711
|
, width0
|
12552
12712
|
, height0
|
12553
12713
|
, timeoutID
|
@@ -12557,6 +12717,31 @@ nv.models.scatter = function() {
|
|
12557
12717
|
, _cache = {}
|
12558
12718
|
;
|
12559
12719
|
|
12720
|
+
//============================================================
|
12721
|
+
// Diff and Cache Utilities
|
12722
|
+
//------------------------------------------------------------
|
12723
|
+
// getDiffs is used to filter unchanged points from the update
|
12724
|
+
// selection. It implicitly updates it's cache when called and
|
12725
|
+
// therefor the diff is based upon the previous invocation NOT
|
12726
|
+
// the previous update.
|
12727
|
+
//
|
12728
|
+
// getDiffs takes a point as its first argument followed by n
|
12729
|
+
// key getter pairs (d, [key, get... key, get]) this approach
|
12730
|
+
// was chosen for efficiency. (The filter will call it a LOT).
|
12731
|
+
//
|
12732
|
+
// It is important to call delCache on point exit to prevent a
|
12733
|
+
// memory leak. It is also needed to prevent invalid caches if
|
12734
|
+
// a new point uses the same series and point id key.
|
12735
|
+
//
|
12736
|
+
// Argument Performance Concerns:
|
12737
|
+
// - Object property lists for key getter pairs would be very
|
12738
|
+
// expensive (points * objects for the GC every update).
|
12739
|
+
// - ES6 function names for implicit keys would be nice but
|
12740
|
+
// they are not guaranteed to be unique.
|
12741
|
+
// - function.toString to obtain implicit keys is possible
|
12742
|
+
// but long object keys are not free (internal hash).
|
12743
|
+
// - Explicit key without objects are the most efficient.
|
12744
|
+
|
12560
12745
|
function getCache(d) {
|
12561
12746
|
var key, val;
|
12562
12747
|
key = d[0].series + ':' + d[1];
|
@@ -12602,7 +12787,7 @@ nv.models.scatter = function() {
|
|
12602
12787
|
});
|
12603
12788
|
|
12604
12789
|
// Setup Scales
|
12605
|
-
var logScale = chart.yScale().
|
12790
|
+
var logScale = (typeof(chart.yScale().base) === "function"); // Only log scale has a method "base()"
|
12606
12791
|
// remap and flatten the data for use in calculating the scales' domains
|
12607
12792
|
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
|
12608
12793
|
d3.merge(
|
@@ -12669,6 +12854,16 @@ nv.models.scatter = function() {
|
|
12669
12854
|
|
12670
12855
|
var sizeDiff = width0 !== width || height0 !== height;
|
12671
12856
|
|
12857
|
+
// Domain Diffs
|
12858
|
+
|
12859
|
+
xDom = xDom || [];
|
12860
|
+
var domainDiff = xDom[0] !== x.domain()[0] || xDom[1] !== x.domain()[1];
|
12861
|
+
xDom = x.domain();
|
12862
|
+
|
12863
|
+
yDom = yDom || [];
|
12864
|
+
domainDiff = domainDiff || yDom[0] !== y.domain()[0] || yDom[1] !== y.domain()[1];
|
12865
|
+
yDom = y.domain();
|
12866
|
+
|
12672
12867
|
// Setup containers and skeleton of chart
|
12673
12868
|
var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);
|
12674
12869
|
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id);
|
@@ -12687,7 +12882,7 @@ nv.models.scatter = function() {
|
|
12687
12882
|
.attr('id', 'nv-edge-clip-' + id)
|
12688
12883
|
.append('rect')
|
12689
12884
|
.attr('transform', 'translate( -10, -10)');
|
12690
|
-
|
12885
|
+
|
12691
12886
|
wrap.select('#nv-edge-clip-' + id + ' rect')
|
12692
12887
|
.attr('width', availableWidth + 20)
|
12693
12888
|
.attr('height', (availableHeight > 0) ? availableHeight + 20 : 0);
|
@@ -12703,20 +12898,23 @@ nv.models.scatter = function() {
|
|
12703
12898
|
|
12704
12899
|
// inject series and point index for reference into voronoi
|
12705
12900
|
if (useVoronoi === true) {
|
12901
|
+
|
12902
|
+
// nuke all voronoi paths on reload and recreate them
|
12903
|
+
wrap.select('.nv-point-paths').selectAll('path').remove();
|
12904
|
+
|
12706
12905
|
var vertices = d3.merge(data.map(function(group, groupIndex) {
|
12707
12906
|
return group.values
|
12708
12907
|
.map(function(point, pointIndex) {
|
12709
12908
|
// *Adding noise to make duplicates very unlikely
|
12710
12909
|
// *Injecting series and point index for reference
|
12711
|
-
|
12712
|
-
*/
|
12910
|
+
// *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.
|
12713
12911
|
var pX = getX(point,pointIndex);
|
12714
12912
|
var pY = getY(point,pointIndex);
|
12715
12913
|
|
12716
|
-
return [nv.utils.NaNtoZero(x(pX))+ Math.random() * 1e-4,
|
12717
|
-
nv.utils.NaNtoZero(y(pY))+ Math.random() * 1e-4,
|
12914
|
+
return [nv.utils.NaNtoZero(x(pX)) + Math.random() * 1e-4,
|
12915
|
+
nv.utils.NaNtoZero(y(pY)) + Math.random() * 1e-4,
|
12718
12916
|
groupIndex,
|
12719
|
-
pointIndex, point];
|
12917
|
+
pointIndex, point];
|
12720
12918
|
})
|
12721
12919
|
.filter(function(pointArray, pointIndex) {
|
12722
12920
|
return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!
|
@@ -12742,6 +12940,18 @@ nv.models.scatter = function() {
|
|
12742
12940
|
[width + 10,-10]
|
12743
12941
|
]);
|
12744
12942
|
|
12943
|
+
// delete duplicates from vertices - essential assumption for d3.geom.voronoi
|
12944
|
+
var epsilon = 1e-4; // Uses 1e-4 to determine equivalence.
|
12945
|
+
vertices = vertices.sort(function(a,b){return ((a[0] - b[0]) || (a[1] - b[1]))});
|
12946
|
+
for (var i = 0; i < vertices.length - 1; ) {
|
12947
|
+
if ((Math.abs(vertices[i][0] - vertices[i+1][0]) < epsilon) &&
|
12948
|
+
(Math.abs(vertices[i][1] - vertices[i+1][1]) < epsilon)) {
|
12949
|
+
vertices.splice(i+1, 1);
|
12950
|
+
} else {
|
12951
|
+
i++;
|
12952
|
+
}
|
12953
|
+
}
|
12954
|
+
|
12745
12955
|
var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
|
12746
12956
|
return {
|
12747
12957
|
'data': bounds.clip(d),
|
@@ -12750,8 +12960,6 @@ nv.models.scatter = function() {
|
|
12750
12960
|
}
|
12751
12961
|
});
|
12752
12962
|
|
12753
|
-
// nuke all voronoi paths on reload and recreate them
|
12754
|
-
wrap.select('.nv-point-paths').selectAll('path').remove();
|
12755
12963
|
var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi);
|
12756
12964
|
var vPointPaths = pointPaths
|
12757
12965
|
.enter().append("svg:path")
|
@@ -12957,20 +13165,47 @@ nv.models.scatter = function() {
|
|
12957
13165
|
return 'translate(' + nv.utils.NaNtoZero(x(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')'
|
12958
13166
|
})
|
12959
13167
|
.remove();
|
12960
|
-
|
12961
|
-
|
12962
|
-
|
12963
|
-
|
12964
|
-
|
12965
|
-
|
12966
|
-
|
12967
|
-
//
|
12968
|
-
|
12969
|
-
|
12970
|
-
|
12971
|
-
|
12972
|
-
|
12973
|
-
|
13168
|
+
|
13169
|
+
//============================================================
|
13170
|
+
// Point Update Optimisation Notes
|
13171
|
+
//------------------------------------------------------------
|
13172
|
+
// The following update selections are filtered with getDiffs
|
13173
|
+
// (defined at the top of this file) this brings a performance
|
13174
|
+
// benefit for charts with large data sets that accumulate a
|
13175
|
+
// subset of changes or additions over time.
|
13176
|
+
//
|
13177
|
+
// Uneccesary and expensive DOM calls are avoided by culling
|
13178
|
+
// unchanged points from the selection in exchange for the
|
13179
|
+
// cheaper overhead of caching and diffing each point first.
|
13180
|
+
//
|
13181
|
+
// Due to the way D3 and NVD3 work, other global changes need
|
13182
|
+
// to be considered in addition to local point properties.
|
13183
|
+
// This is a potential source of bugs (if any of the global
|
13184
|
+
// changes that possibly affect points are missed).
|
13185
|
+
|
13186
|
+
// Update Point Positions [x, y]
|
13187
|
+
points.filter(function (d) {
|
13188
|
+
// getDiffs must always be called to update cache
|
13189
|
+
return getDiffs(d, 'x', getX, 'y', getY) ||
|
13190
|
+
scaleDiff || sizeDiff || domainDiff;
|
13191
|
+
})
|
13192
|
+
.watchTransition(renderWatch, 'scatter points')
|
13193
|
+
.attr('transform', function (d) {
|
13194
|
+
return 'translate(' +
|
13195
|
+
nv.utils.NaNtoZero(x(getX(d[0], d[1]))) + ',' +
|
13196
|
+
nv.utils.NaNtoZero(y(getY(d[0], d[1]))) + ')'
|
13197
|
+
});
|
13198
|
+
|
13199
|
+
// Update Point Appearance [shape, size]
|
13200
|
+
points.filter(function (d) {
|
13201
|
+
// getDiffs must always be called to update cache
|
13202
|
+
return getDiffs(d, 'shape', getShape, 'size', getSize) ||
|
13203
|
+
scaleDiff || sizeDiff || domainDiff;
|
13204
|
+
})
|
13205
|
+
.watchTransition(renderWatch, 'scatter points')
|
13206
|
+
.attr('d', nv.utils.symbol()
|
13207
|
+
.type(function (d) { return getShape(d[0]) })
|
13208
|
+
.size(function (d) { return z(getSize(d[0], d[1])) })
|
12974
13209
|
);
|
12975
13210
|
|
12976
13211
|
// add label a label to scatter chart
|
@@ -14625,7 +14860,7 @@ nv.models.stackedAreaChart = function() {
|
|
14625
14860
|
|
14626
14861
|
interactiveLayer.dispatch.on('elementMousemove', function(e) {
|
14627
14862
|
stacked.clearHighlights();
|
14628
|
-
var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0, allNullValues = true;
|
14863
|
+
var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0, allNullValues = true, atleastOnePoint = false;
|
14629
14864
|
data
|
14630
14865
|
.filter(function(series, i) {
|
14631
14866
|
series.seriesIndex = i;
|
@@ -14635,7 +14870,13 @@ nv.models.stackedAreaChart = function() {
|
|
14635
14870
|
pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
|
14636
14871
|
var point = series.values[pointIndex];
|
14637
14872
|
var pointYValue = chart.y()(point, pointIndex);
|
14638
|
-
if (pointYValue != null) {
|
14873
|
+
if (pointYValue != null && pointYValue > 0) {
|
14874
|
+
stacked.highlightPoint(i, pointIndex, true);
|
14875
|
+
atleastOnePoint = true;
|
14876
|
+
}
|
14877
|
+
|
14878
|
+
// Draw at least one point if all values are zero.
|
14879
|
+
if (i === (data.length - 1) && !atleastOnePoint) {
|
14639
14880
|
stacked.highlightPoint(i, pointIndex, true);
|
14640
14881
|
}
|
14641
14882
|
if (typeof point === 'undefined') return;
|
@@ -14914,7 +15155,13 @@ nv.models.sunburst = function() {
|
|
14914
15155
|
, labelFormat = function(d){if(mode === 'count'){return d.name + ' #' + d.value}else{return d.name + ' ' + (d.value || d.size)}}
|
14915
15156
|
, labelThreshold = 0.02
|
14916
15157
|
, sort = function(d1, d2){return d1.name > d2.name;}
|
14917
|
-
, key = function(d,i){
|
15158
|
+
, key = function(d,i){
|
15159
|
+
if (d.parent !== undefined) {
|
15160
|
+
return d.name + '-' + d.parent.name + '-' + i;
|
15161
|
+
} else {
|
15162
|
+
return d.name;
|
15163
|
+
}
|
15164
|
+
}
|
14918
15165
|
, groupColorByParent = true
|
14919
15166
|
, duration = 500
|
14920
15167
|
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd');
|
@@ -15420,6 +15667,6 @@ nv.models.sunburstChart = function() {
|
|
15420
15667
|
|
15421
15668
|
};
|
15422
15669
|
|
15423
|
-
nv.version = "1.8.
|
15670
|
+
nv.version = "1.8.6";
|
15424
15671
|
})();
|
15425
15672
|
//# sourceMappingURL=nv.d3.js.map
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: novus-nvd3-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dbackowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -183,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
requirements: []
|
185
185
|
rubyforge_project:
|
186
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.6.11
|
187
187
|
signing_key:
|
188
188
|
specification_version: 4
|
189
189
|
summary: Nvd3 - reusable chart library for d3.js.
|