novus-nvd3-rails 1.8.3 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd609fdf8f388b5244547d270b2f5cb244e7ad2b
4
- data.tar.gz: 5a954a6949b7fefe57819aa489330d36e34d693f
3
+ metadata.gz: a5f121514df13fbf7e5af57fa40e09c4656fc5d4
4
+ data.tar.gz: f11b3b9f8aa1ef76718a486f4cf7650c9227c972
5
5
  SHA512:
6
- metadata.gz: fe70dd05dce10fca74e1996cc6188f9b968755455a8a2472b0f0af81b8a11be7f361b95f18ec8eb03012b0d01c4fba21d3f4e2e65ae7c6afa50ad68c20a9d893
7
- data.tar.gz: 6c2ecaa4a7eef83d6a32cb422125c449d589af58a079907d415905811be280d549be4e531c0dc10db51c43596ad4c30764e6777c3d4bdd328f4415d963f0d69d
6
+ metadata.gz: ddd3c9ba4788e2ad49037fda46064a0a66e964f68f1326ed1aab266908a90b35bcfaa7c283d3cf98c1db79a3f527eb7fbf19ada7ea1c776b9b22e88d72ba16ef
7
+ data.tar.gz: 0ac7e602cddcd6c0fdc6f10813e18c264332dc2e67006674b55a18f55fd04dc890fd503689f7391849af12b50854350bed0034cadc92c7218d50007f82dce076
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.2
4
+ - 2.3.1
@@ -1,7 +1,7 @@
1
1
  module Novus
2
2
  module Nvd3
3
3
  module Rails
4
- VERSION = "1.8.3"
4
+ VERSION = "1.8.4"
5
5
  end
6
6
  end
7
7
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "bundler", "~> 1.12"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency 'rails', '4.2.6'
24
24
  spec.add_development_dependency 'rspec-rails', '~> 3.0'
@@ -1,4 +1,4 @@
1
- /* nvd3 version 1.8.3 (https://github.com/novus/nvd3) 2016-04-26 */
1
+ /* nvd3 version 1.8.4 (https://github.com/novus/nvd3) 2016-07-03 */
2
2
  (function(){
3
3
 
4
4
  // set up main nv object
@@ -198,7 +198,7 @@ nv.interactiveGuideline = function() {
198
198
  , showGuideLine = true
199
199
  , svgContainer = null // Must pass the chart's svg, we'll use its mousemove event.
200
200
  , tooltip = nv.models.tooltip()
201
- , isMSIE = "ActiveXObject" in window // Checkt if IE by looking for activeX.
201
+ , isMSIE = window.ActiveXObject// Checkt if IE by looking for activeX. (excludes IE11)
202
202
  ;
203
203
 
204
204
  tooltip
@@ -545,7 +545,6 @@ nv.models.tooltip = function() {
545
545
  , distance = 25 // Distance to offset tooltip from the mouse location.
546
546
  , snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
547
547
  , classes = null // Attaches additional CSS classes to the tooltip DIV that is created.
548
- , chartContainer = null // Parent dom element of the SVG that holds the chart.
549
548
  , hidden = true // Start off hidden, toggle with hide/show functions below.
550
549
  , hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide().
551
550
  , tooltip = null // d3 select of the tooltip div.
@@ -556,20 +555,6 @@ nv.models.tooltip = function() {
556
555
  , nvPointerEventsClass = "nv-pointer-events-none" // CSS class to specify whether element should not have mouse events.
557
556
  ;
558
557
 
559
- /*
560
- Function that returns the position (relative to the viewport) the tooltip should be placed in.
561
- Should return: {
562
- left: <leftPos>,
563
- top: <topPos>
564
- }
565
- */
566
- var position = function() {
567
- return {
568
- left: d3.event !== null ? d3.event.clientX : 0,
569
- top: d3.event !== null ? d3.event.clientY : 0
570
- };
571
- };
572
-
573
558
  // Format function for the tooltip values column.
574
559
  var valueFormatter = function(d, i) {
575
560
  return d;
@@ -629,6 +614,10 @@ nv.models.tooltip = function() {
629
614
  .classed("value",true)
630
615
  .html(function(p, i) { return valueFormatter(p.value, i) });
631
616
 
617
+ trowEnter.filter(function (p,i) { return p.percent !== undefined }).append("td")
618
+ .classed("percent", true)
619
+ .html(function(p, i) { return "(" + d3.format('%')(p.percent) + ")" });
620
+
632
621
  trowEnter.selectAll("td").each(function(p) {
633
622
  if (p.highlight) {
634
623
  var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]);
@@ -647,6 +636,31 @@ nv.models.tooltip = function() {
647
636
 
648
637
  };
649
638
 
639
+ /*
640
+ Function that returns the position (relative to the viewport/document.body)
641
+ the tooltip should be placed in.
642
+ Should return: {
643
+ left: <leftPos>,
644
+ top: <topPos>
645
+ }
646
+ */
647
+ var position = function() {
648
+ var pos = {
649
+ left: d3.event !== null ? d3.event.clientX : 0,
650
+ top: d3.event !== null ? d3.event.clientY : 0
651
+ };
652
+
653
+ if(getComputedStyle(document.body).transform != 'none') {
654
+ // Take the offset into account, as now the tooltip is relative
655
+ // to document.body.
656
+ var client = document.body.getBoundingClientRect();
657
+ pos.left -= client.left;
658
+ pos.top -= client.top;
659
+ }
660
+
661
+ return pos;
662
+ };
663
+
650
664
  var dataSeriesExists = function(d) {
651
665
  if (d && d.series) {
652
666
  if (nv.utils.isArray(d.series)) {
@@ -734,7 +748,7 @@ nv.models.tooltip = function() {
734
748
  } else {
735
749
  // using tooltip.style('transform') returns values un-usable for tween
736
750
  var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)';
737
- var new_translate = 'translate(' + left + 'px, ' + top + 'px)';
751
+ var new_translate = 'translate(' + Math.round(left) + 'px, ' + Math.round(top) + 'px)';
738
752
  var translateInterpolator = d3.interpolateString(old_translate, new_translate);
739
753
  var is_hidden = tooltip.style('opacity') < 0.1;
740
754
 
@@ -762,11 +776,10 @@ nv.models.tooltip = function() {
762
776
  // Creates new tooltip container, or uses existing one on DOM.
763
777
  function initTooltip() {
764
778
  if (!tooltip || !tooltip.node()) {
765
- var container = chartContainer ? chartContainer : document.body;
766
779
  // Create new tooltip div if it doesn't exist on DOM.
767
780
 
768
781
  var data = [1];
769
- tooltip = d3.select(container).selectAll('.nvtooltip').data(data);
782
+ tooltip = d3.select(document.body).selectAll('.nvtooltip').data(data);
770
783
 
771
784
  tooltip.enter().append('div')
772
785
  .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip"))
@@ -812,7 +825,6 @@ nv.models.tooltip = function() {
812
825
  distance: {get: function(){return distance;}, set: function(_){distance=_;}},
813
826
  snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}},
814
827
  classes: {get: function(){return classes;}, set: function(_){classes=_;}},
815
- chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}},
816
828
  enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}},
817
829
  hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}},
818
830
  contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}},
@@ -823,6 +835,10 @@ nv.models.tooltip = function() {
823
835
  position: {get: function(){return position;}, set: function(_){position=_;}},
824
836
 
825
837
  // Deprecated options
838
+ chartContainer: {get: function(){return document.body;}, set: function(_){
839
+ // deprecated after 1.8.3
840
+ nv.deprecated('chartContainer', 'feature removed after 1.8.3');
841
+ }},
826
842
  fixedTop: {get: function(){return null;}, set: function(_){
827
843
  // deprecated after 1.8.1
828
844
  nv.deprecated('fixedTop', 'feature removed after 1.8.1');
@@ -1550,7 +1566,7 @@ nv.utils.arrayEquals = function (array1, array2) {
1550
1566
  if (!array1 || !array2)
1551
1567
  return false;
1552
1568
 
1553
- // compare lengths - can save a lot of time
1569
+ // compare lengths - can save a lot of time
1554
1570
  if (array1.length != array2.length)
1555
1571
  return false;
1556
1572
 
@@ -1567,7 +1583,8 @@ nv.utils.arrayEquals = function (array1, array2) {
1567
1583
  }
1568
1584
  }
1569
1585
  return true;
1570
- };nv.models.axis = function() {
1586
+ };
1587
+ nv.models.axis = function() {
1571
1588
  "use strict";
1572
1589
 
1573
1590
  //============================================================
@@ -1765,7 +1782,7 @@ nv.utils.arrayEquals = function (array1, array2) {
1765
1782
  axisLabel
1766
1783
  .style('text-anchor', rotateYLabel ? 'middle' : 'begin')
1767
1784
  .attr('transform', rotateYLabel ? 'rotate(90)' : '')
1768
- .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
1785
+ .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
1769
1786
  .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding());
1770
1787
  if (showMaxMin) {
1771
1788
  axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -2533,9 +2550,11 @@ nv.models.bullet = function() {
2533
2550
  , reverse = false
2534
2551
  , ranges = function(d) { return d.ranges }
2535
2552
  , markers = function(d) { return d.markers ? d.markers : [] }
2553
+ , markerLines = function(d) { return d.markerLines ? d.markerLines : [0] }
2536
2554
  , measures = function(d) { return d.measures }
2537
2555
  , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }
2538
2556
  , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }
2557
+ , markerLineLabels = function(d) { return d.markerLineLabels ? d.markerLineLabels : [] }
2539
2558
  , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }
2540
2559
  , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
2541
2560
  , width = 380
@@ -2567,14 +2586,17 @@ nv.models.bullet = function() {
2567
2586
 
2568
2587
  var rangez = ranges.call(this, d, i).slice(),
2569
2588
  markerz = markers.call(this, d, i).slice(),
2589
+ markerLinez = markerLines.call(this, d, i).slice().sort(d3.descending),
2570
2590
  measurez = measures.call(this, d, i).slice(),
2571
2591
  rangeLabelz = rangeLabels.call(this, d, i).slice(),
2572
2592
  markerLabelz = markerLabels.call(this, d, i).slice(),
2593
+ markerLineLabelz = markerLineLabels.call(this, d, i).slice(),
2573
2594
  measureLabelz = measureLabels.call(this, d, i).slice();
2574
2595
 
2575
2596
  // Sort labels according to their sorted values
2576
2597
  sortLabels(rangeLabelz, rangez);
2577
2598
  sortLabels(markerLabelz, markerz);
2599
+ sortLabels(markerLineLabelz, markerLinez);
2578
2600
  sortLabels(measureLabelz, measurez);
2579
2601
 
2580
2602
  // sort values descending
@@ -2702,6 +2724,48 @@ nv.models.bullet = function() {
2702
2724
  .data(markerData)
2703
2725
  .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' });
2704
2726
 
2727
+ var markerLinesData = markerLinez.map( function(marker, index) {
2728
+ return {value: marker, label: markerLineLabelz[index]}
2729
+ });
2730
+ gEnter
2731
+ .selectAll("path.nv-markerLine")
2732
+ .data(markerLinesData)
2733
+ .enter()
2734
+ .append('line')
2735
+ .attr('cursor', '')
2736
+ .attr('class', 'nv-markerLine')
2737
+ .attr('x1', function(d) { return x1(d.value) })
2738
+ .attr('y1', '2')
2739
+ .attr('x2', function(d) { return x1(d.value) })
2740
+ .attr('y2', availableHeight - 2)
2741
+ .on('mouseover', function(d) {
2742
+ dispatch.elementMouseover({
2743
+ value: d.value,
2744
+ label: d.label || 'Previous',
2745
+ color: d3.select(this).style("fill"),
2746
+ pos: [x1(d.value), availableHeight/2]
2747
+ })
2748
+
2749
+ })
2750
+ .on('mousemove', function(d) {
2751
+ dispatch.elementMousemove({
2752
+ value: d.value,
2753
+ label: d.label || 'Previous',
2754
+ color: d3.select(this).style("fill")
2755
+ })
2756
+ })
2757
+ .on('mouseout', function(d, i) {
2758
+ dispatch.elementMouseout({
2759
+ value: d.value,
2760
+ label: d.label || 'Previous',
2761
+ color: d3.select(this).style("fill")
2762
+ })
2763
+ });
2764
+
2765
+ g.selectAll("path.nv-markerLines")
2766
+ .data(markerLinesData)
2767
+ .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' });
2768
+
2705
2769
  wrap.selectAll('.nv-range')
2706
2770
  .on('mouseover', function(d,i) {
2707
2771
  var label = rangeLabelz[i] || defaultRangeLabels[i];
@@ -3429,7 +3493,7 @@ nv.models.cumulativeLineChart = function() {
3429
3493
  .datum(data)
3430
3494
  .call(legend);
3431
3495
 
3432
- if ( margin.top != legend.height()) {
3496
+ if (legend.height() > margin.top) {
3433
3497
  margin.top = legend.height();
3434
3498
  availableHeight = nv.utils.availableHeight(height, container, margin);
3435
3499
  }
@@ -3684,7 +3748,6 @@ nv.models.cumulativeLineChart = function() {
3684
3748
 
3685
3749
  var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex);
3686
3750
  interactiveLayer.tooltip
3687
- .chartContainer(that.parentNode)
3688
3751
  .valueFormatter(function(d,i) {
3689
3752
  return yAxis.tickFormat()(d);
3690
3753
  })
@@ -4228,7 +4291,7 @@ nv.models.discreteBarChart = function() {
4228
4291
  .datum(data)
4229
4292
  .call(legend);
4230
4293
 
4231
- if ( margin.top != legend.height()) {
4294
+ if (legend.height() > margin.top) {
4232
4295
  margin.top = legend.height();
4233
4296
  availableHeight = nv.utils.availableHeight(height, container, margin);
4234
4297
  }
@@ -4236,11 +4299,11 @@ nv.models.discreteBarChart = function() {
4236
4299
  wrap.select('.nv-legendWrap')
4237
4300
  .attr('transform', 'translate(0,' + (-margin.top) +')')
4238
4301
  }
4239
-
4302
+
4240
4303
  if (rightAlignYAxis) {
4241
4304
  g.select(".nv-y.nv-axis")
4242
4305
  .attr("transform", "translate(" + availableWidth + ",0)");
4243
- }
4306
+ }
4244
4307
 
4245
4308
  // Main Chart Component(s)
4246
4309
  discretebar
@@ -4551,6 +4614,299 @@ nv.models.distribution = function() {
4551
4614
 
4552
4615
  return chart;
4553
4616
  }
4617
+ nv.models.focus = function(content) {
4618
+ "use strict";
4619
+
4620
+ //============================================================
4621
+ // Public Variables with Default Settings
4622
+ //------------------------------------------------------------
4623
+
4624
+ var content = content || nv.models.line()
4625
+ , xAxis = nv.models.axis()
4626
+ , yAxis = nv.models.axis()
4627
+ , brush = d3.svg.brush()
4628
+ ;
4629
+
4630
+ var margin = {top: 10, right: 0, bottom: 30, left: 0}
4631
+ , color = nv.utils.defaultColor()
4632
+ , width = null
4633
+ , height = 70
4634
+ , showXAxis = true
4635
+ , showYAxis = false
4636
+ , rightAlignYAxis = false
4637
+ , ticks = null
4638
+ , x
4639
+ , y
4640
+ , brushExtent = null
4641
+ , duration = 250
4642
+ , dispatch = d3.dispatch('brush', 'onBrush', 'renderEnd')
4643
+ ;
4644
+
4645
+ content.interactive(false);
4646
+ content.pointActive(function(d) { return false; });
4647
+
4648
+ //============================================================
4649
+ // Private Variables
4650
+ //------------------------------------------------------------
4651
+
4652
+ var renderWatch = nv.utils.renderWatch(dispatch, duration);
4653
+
4654
+ function chart(selection) {
4655
+ renderWatch.reset();
4656
+ renderWatch.models(content);
4657
+ if (showXAxis) renderWatch.models(xAxis);
4658
+ if (showYAxis) renderWatch.models(yAxis);
4659
+
4660
+ selection.each(function(data) {
4661
+ var container = d3.select(this);
4662
+ nv.utils.initSVG(container);
4663
+ var availableWidth = nv.utils.availableWidth(width, container, margin),
4664
+ availableHeight = height - margin.top - margin.bottom;
4665
+
4666
+ chart.update = function() {
4667
+ if( duration === 0 ) {
4668
+ container.call( chart );
4669
+ } else {
4670
+ container.transition().duration(duration).call(chart);
4671
+ }
4672
+ };
4673
+ chart.container = this;
4674
+
4675
+ // Setup Scales
4676
+ x = content.xScale();
4677
+ y = content.yScale();
4678
+
4679
+ // Setup containers and skeleton of chart
4680
+ var wrap = container.selectAll('g.nv-focus').data([data]);
4681
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-focus').append('g');
4682
+ var g = wrap.select('g');
4683
+
4684
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
4685
+
4686
+ gEnter.append('g').attr('class', 'nv-background').append('rect');
4687
+ gEnter.append('g').attr('class', 'nv-x nv-axis');
4688
+ gEnter.append('g').attr('class', 'nv-y nv-axis');
4689
+ gEnter.append('g').attr('class', 'nv-contentWrap');
4690
+ gEnter.append('g').attr('class', 'nv-brushBackground');
4691
+ gEnter.append('g').attr('class', 'nv-x nv-brush');
4692
+
4693
+ if (rightAlignYAxis) {
4694
+ g.select(".nv-y.nv-axis")
4695
+ .attr("transform", "translate(" + availableWidth + ",0)");
4696
+ }
4697
+
4698
+ g.select('.nv-background rect')
4699
+ .attr('width', availableWidth)
4700
+ .attr('height', availableHeight);
4701
+
4702
+ content
4703
+ .width(availableWidth)
4704
+ .height(availableHeight)
4705
+ .color(data.map(function(d,i) {
4706
+ return d.color || color(d, i);
4707
+ }).filter(function(d,i) { return !data[i].disabled; }));
4708
+
4709
+ var contentWrap = g.select('.nv-contentWrap')
4710
+ .datum(data.filter(function(d) { return !d.disabled; }));
4711
+
4712
+ d3.transition(contentWrap).call(content);
4713
+
4714
+ // Setup Brush
4715
+ brush
4716
+ .x(x)
4717
+ .on('brush', function() {
4718
+ onBrush();
4719
+ });
4720
+
4721
+ if (brushExtent) brush.extent(brushExtent);
4722
+
4723
+ var brushBG = g.select('.nv-brushBackground').selectAll('g')
4724
+ .data([brushExtent || brush.extent()]);
4725
+
4726
+ var brushBGenter = brushBG.enter()
4727
+ .append('g');
4728
+
4729
+ brushBGenter.append('rect')
4730
+ .attr('class', 'left')
4731
+ .attr('x', 0)
4732
+ .attr('y', 0)
4733
+ .attr('height', availableHeight);
4734
+
4735
+ brushBGenter.append('rect')
4736
+ .attr('class', 'right')
4737
+ .attr('x', 0)
4738
+ .attr('y', 0)
4739
+ .attr('height', availableHeight);
4740
+
4741
+ var gBrush = g.select('.nv-x.nv-brush')
4742
+ .call(brush);
4743
+ gBrush.selectAll('rect')
4744
+ .attr('height', availableHeight);
4745
+ gBrush.selectAll('.resize').append('path').attr('d', resizePath);
4746
+
4747
+ onBrush();
4748
+
4749
+ g.select('.nv-background rect')
4750
+ .attr('width', availableWidth)
4751
+ .attr('height', availableHeight);
4752
+
4753
+ if (showXAxis) {
4754
+ xAxis.scale(x)
4755
+ ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
4756
+ .tickSize(-availableHeight, 0);
4757
+
4758
+ g.select('.nv-x.nv-axis')
4759
+ .attr('transform', 'translate(0,' + y.range()[0] + ')');
4760
+ d3.transition(g.select('.nv-x.nv-axis'))
4761
+ .call(xAxis);
4762
+ }
4763
+
4764
+ if (showYAxis) {
4765
+ yAxis
4766
+ .scale(y)
4767
+ ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
4768
+ .tickSize( -availableWidth, 0);
4769
+
4770
+ d3.transition(g.select('.nv-y.nv-axis'))
4771
+ .call(yAxis);
4772
+ }
4773
+
4774
+ g.select('.nv-x.nv-axis')
4775
+ .attr('transform', 'translate(0,' + y.range()[0] + ')');
4776
+
4777
+ //============================================================
4778
+ // Event Handling/Dispatching (in chart's scope)
4779
+ //------------------------------------------------------------
4780
+
4781
+ //============================================================
4782
+ // Functions
4783
+ //------------------------------------------------------------
4784
+
4785
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
4786
+ function resizePath(d) {
4787
+ var e = +(d == 'e'),
4788
+ x = e ? 1 : -1,
4789
+ y = availableHeight / 3;
4790
+ return 'M' + (0.5 * x) + ',' + y
4791
+ + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
4792
+ + 'V' + (2 * y - 6)
4793
+ + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y)
4794
+ + 'Z'
4795
+ + 'M' + (2.5 * x) + ',' + (y + 8)
4796
+ + 'V' + (2 * y - 8)
4797
+ + 'M' + (4.5 * x) + ',' + (y + 8)
4798
+ + 'V' + (2 * y - 8);
4799
+ }
4800
+
4801
+
4802
+ function updateBrushBG() {
4803
+ if (!brush.empty()) brush.extent(brushExtent);
4804
+ brushBG
4805
+ .data([brush.empty() ? x.domain() : brushExtent])
4806
+ .each(function(d,i) {
4807
+ var leftWidth = x(d[0]) - x.range()[0],
4808
+ rightWidth = availableWidth - x(d[1]);
4809
+ d3.select(this).select('.left')
4810
+ .attr('width', leftWidth < 0 ? 0 : leftWidth);
4811
+
4812
+ d3.select(this).select('.right')
4813
+ .attr('x', x(d[1]))
4814
+ .attr('width', rightWidth < 0 ? 0 : rightWidth);
4815
+ });
4816
+ }
4817
+
4818
+
4819
+ function onBrush() {
4820
+ brushExtent = brush.empty() ? null : brush.extent();
4821
+ var extent = brush.empty() ? x.domain() : brush.extent();
4822
+
4823
+ //The brush extent cannot be less than one. If it is, don't update the line chart.
4824
+ if (Math.abs(extent[0] - extent[1]) <= 1) {
4825
+ return;
4826
+ }
4827
+
4828
+ dispatch.brush({extent: extent, brush: brush});
4829
+
4830
+ updateBrushBG();
4831
+ dispatch.onBrush(extent);
4832
+ }
4833
+
4834
+
4835
+ });
4836
+
4837
+ renderWatch.renderEnd('focus immediate');
4838
+ return chart;
4839
+ }
4840
+
4841
+
4842
+ //============================================================
4843
+ // Event Handling/Dispatching (out of chart's scope)
4844
+ //------------------------------------------------------------
4845
+
4846
+ //============================================================
4847
+ // Expose Public Variables
4848
+ //------------------------------------------------------------
4849
+
4850
+ // expose chart's sub-components
4851
+ chart.dispatch = dispatch;
4852
+ chart.content = content;
4853
+ chart.brush = brush;
4854
+ chart.xAxis = xAxis;
4855
+ chart.yAxis = yAxis;
4856
+ chart.options = nv.utils.optionsFunc.bind(chart);
4857
+
4858
+ chart._options = Object.create({}, {
4859
+ // simple options, just get/set the necessary values
4860
+ width: {get: function(){return width;}, set: function(_){width=_;}},
4861
+ height: {get: function(){return height;}, set: function(_){height=_;}},
4862
+ showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
4863
+ showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
4864
+ brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
4865
+
4866
+ // options that require extra logic in the setter
4867
+ margin: {get: function(){return margin;}, set: function(_){
4868
+ margin.top = _.top !== undefined ? _.top : margin.top;
4869
+ margin.right = _.right !== undefined ? _.right : margin.right;
4870
+ margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
4871
+ margin.left = _.left !== undefined ? _.left : margin.left;
4872
+ }},
4873
+ duration: {get: function(){return duration;}, set: function(_){
4874
+ duration = _;
4875
+ renderWatch.reset(duration);
4876
+ content.duration(duration);
4877
+ xAxis.duration(duration);
4878
+ yAxis.duration(duration);
4879
+ }},
4880
+ color: {get: function(){return color;}, set: function(_){
4881
+ color = nv.utils.getColor(_);
4882
+ content.color(color);
4883
+ }},
4884
+ interpolate: {get: function(){return content.interpolate();}, set: function(_){
4885
+ content.interpolate(_);
4886
+ }},
4887
+ xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
4888
+ xAxis.tickFormat(_);
4889
+ }},
4890
+ yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
4891
+ yAxis.tickFormat(_);
4892
+ }},
4893
+ x: {get: function(){return content.x();}, set: function(_){
4894
+ content.x(_);
4895
+ }},
4896
+ y: {get: function(){return content.y();}, set: function(_){
4897
+ content.y(_);
4898
+ }},
4899
+ rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
4900
+ rightAlignYAxis = _;
4901
+ yAxis.orient( rightAlignYAxis ? 'right' : 'left');
4902
+ }},
4903
+ });
4904
+
4905
+ nv.utils.inheritOptions(chart, content);
4906
+ nv.utils.initOptions(chart);
4907
+
4908
+ return chart;
4909
+ };
4554
4910
  nv.models.forceDirectedGraph = function() {
4555
4911
  "use strict";
4556
4912
 
@@ -4751,6 +5107,7 @@ nv.models.furiousLegend = function() {
4751
5107
  , width = 400
4752
5108
  , height = 20
4753
5109
  , getKey = function(d) { return d.key }
5110
+ , keyFormatter = function (d) { return d }
4754
5111
  , color = nv.utils.getColor()
4755
5112
  , maxKeyLength = 20 //default value for key lengths
4756
5113
  , align = true
@@ -4902,7 +5259,7 @@ nv.models.furiousLegend = function() {
4902
5259
 
4903
5260
  seriesText
4904
5261
  .attr('fill', setTextColor)
4905
- .text(getKey);
5262
+ .text(function (d) { return keyFormatter(getKey(d)) });
4906
5263
 
4907
5264
  //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
4908
5265
  // NEW ALIGNING CODE, TODO: clean up
@@ -4921,10 +5278,10 @@ nv.models.furiousLegend = function() {
4921
5278
  var seriesWidths = [];
4922
5279
  series.each(function(d,i) {
4923
5280
  var legendText;
4924
- if (getKey(d) && (getKey(d).length > maxKeyLength)) {
4925
- var trimmedKey = getKey(d).substring(0, maxKeyLength);
5281
+ if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {
5282
+ var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);
4926
5283
  legendText = d3.select(this).select('text').text(trimmedKey + "...");
4927
- d3.select(this).append("svg:title").text(getKey(d));
5284
+ d3.select(this).append("svg:title").text(keyFormatter(getKey(d)));
4928
5285
  } else {
4929
5286
  legendText = d3.select(this).select('text');
4930
5287
  }
@@ -5059,17 +5416,18 @@ nv.models.furiousLegend = function() {
5059
5416
 
5060
5417
  chart._options = Object.create({}, {
5061
5418
  // simple options, just get/set the necessary values
5062
- width: {get: function(){return width;}, set: function(_){width=_;}},
5063
- height: {get: function(){return height;}, set: function(_){height=_;}},
5064
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
5065
- align: {get: function(){return align;}, set: function(_){align=_;}},
5066
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
5067
- maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
5068
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
5069
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
5070
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
5071
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
5072
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
5419
+ width: {get: function(){return width;}, set: function(_){width=_;}},
5420
+ height: {get: function(){return height;}, set: function(_){height=_;}},
5421
+ key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
5422
+ keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
5423
+ align: {get: function(){return align;}, set: function(_){align=_;}},
5424
+ rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
5425
+ maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
5426
+ padding: {get: function(){return padding;}, set: function(_){padding=_;}},
5427
+ updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
5428
+ radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
5429
+ expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
5430
+ vers: {get: function(){return vers;}, set: function(_){vers=_;}},
5073
5431
 
5074
5432
  // options that require extra logic in the setter
5075
5433
  margin: {get: function(){return margin;}, set: function(_){
@@ -5435,7 +5793,7 @@ nv.models.historicalBarChart = function(bar_model) {
5435
5793
  .datum(data)
5436
5794
  .call(legend);
5437
5795
 
5438
- if ( margin.top != legend.height()) {
5796
+ if (legend.height() > margin.top) {
5439
5797
  margin.top = legend.height();
5440
5798
  availableHeight = nv.utils.availableHeight(height, container, margin);
5441
5799
  }
@@ -5526,7 +5884,6 @@ nv.models.historicalBarChart = function(bar_model) {
5526
5884
 
5527
5885
  var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));
5528
5886
  interactiveLayer.tooltip
5529
- .chartContainer(that.parentNode)
5530
5887
  .valueFormatter(function(d,i) {
5531
5888
  return yAxis.tickFormat()(d);
5532
5889
  })
@@ -5730,6 +6087,7 @@ nv.models.legend = function() {
5730
6087
  , width = 400
5731
6088
  , height = 20
5732
6089
  , getKey = function(d) { return d.key }
6090
+ , keyFormatter = function (d) { return d }
5733
6091
  , color = nv.utils.getColor()
5734
6092
  , maxKeyLength = 20 //default value for key lengths
5735
6093
  , align = true
@@ -5889,7 +6247,7 @@ nv.models.legend = function() {
5889
6247
 
5890
6248
  seriesText
5891
6249
  .attr('fill', setTextColor)
5892
- .text(getKey);
6250
+ .text(function (d) { return keyFormatter(getKey(d)) });
5893
6251
 
5894
6252
  //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
5895
6253
  // NEW ALIGNING CODE, TODO: clean up
@@ -5899,10 +6257,10 @@ nv.models.legend = function() {
5899
6257
  var seriesWidths = [];
5900
6258
  series.each(function(d,i) {
5901
6259
  var legendText;
5902
- if (getKey(d) && (getKey(d).length > maxKeyLength)) {
5903
- var trimmedKey = getKey(d).substring(0, maxKeyLength);
6260
+ if (keyFormatter(getKey(d)) && keyFormatter(getKey(d)).length > maxKeyLength) {
6261
+ var trimmedKey = keyFormatter(getKey(d)).substring(0, maxKeyLength);
5904
6262
  legendText = d3.select(this).select('text').text(trimmedKey + "...");
5905
- d3.select(this).append("svg:title").text(getKey(d));
6263
+ d3.select(this).append("svg:title").text(keyFormatter(getKey(d)));
5906
6264
  } else {
5907
6265
  legendText = d3.select(this).select('text');
5908
6266
  }
@@ -6070,17 +6428,18 @@ nv.models.legend = function() {
6070
6428
 
6071
6429
  chart._options = Object.create({}, {
6072
6430
  // simple options, just get/set the necessary values
6073
- width: {get: function(){return width;}, set: function(_){width=_;}},
6074
- height: {get: function(){return height;}, set: function(_){height=_;}},
6075
- key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
6076
- align: {get: function(){return align;}, set: function(_){align=_;}},
6431
+ width: {get: function(){return width;}, set: function(_){width=_;}},
6432
+ height: {get: function(){return height;}, set: function(_){height=_;}},
6433
+ key: {get: function(){return getKey;}, set: function(_){getKey=_;}},
6434
+ keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}},
6435
+ align: {get: function(){return align;}, set: function(_){align=_;}},
6077
6436
  maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}},
6078
- rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
6079
- padding: {get: function(){return padding;}, set: function(_){padding=_;}},
6080
- updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
6081
- radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
6082
- expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
6083
- vers: {get: function(){return vers;}, set: function(_){vers=_;}},
6437
+ rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}},
6438
+ padding: {get: function(){return padding;}, set: function(_){padding=_;}},
6439
+ updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}},
6440
+ radioButtonMode:{get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}},
6441
+ expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}},
6442
+ vers: {get: function(){return vers;}, set: function(_){vers=_;}},
6084
6443
 
6085
6444
  // options that require extra logic in the setter
6086
6445
  margin: {get: function(){return margin;}, set: function(_){
@@ -6340,14 +6699,10 @@ nv.models.lineChart = function() {
6340
6699
  , legend = nv.models.legend()
6341
6700
  , interactiveLayer = nv.interactiveGuideline()
6342
6701
  , tooltip = nv.models.tooltip()
6343
- , lines2 = nv.models.line()
6344
- , x2Axis = nv.models.axis()
6345
- , y2Axis = nv.models.axis()
6346
- , brush = d3.svg.brush()
6702
+ , focus = nv.models.focus(nv.models.line())
6347
6703
  ;
6348
6704
 
6349
6705
  var margin = {top: 30, right: 20, bottom: 50, left: 60}
6350
- , margin2 = {top: 0, right: 20, bottom: 20, left: 60}
6351
6706
  , color = nv.utils.defaultColor()
6352
6707
  , width = null
6353
6708
  , height = null
@@ -6359,17 +6714,11 @@ nv.models.lineChart = function() {
6359
6714
  , useInteractiveGuideline = false
6360
6715
  , x
6361
6716
  , y
6362
- , x2
6363
- , y2
6364
6717
  , focusEnable = false
6365
- , focusShowAxisY = false
6366
- , focusShowAxisX = true
6367
- , focusHeight = 50
6368
- , brushExtent = null
6369
6718
  , state = nv.utils.state()
6370
6719
  , defaultState = null
6371
6720
  , noData = null
6372
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState', 'renderEnd')
6721
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd')
6373
6722
  , duration = 250
6374
6723
  ;
6375
6724
 
@@ -6378,19 +6727,13 @@ nv.models.lineChart = function() {
6378
6727
  yAxis.orient(rightAlignYAxis ? 'right' : 'left');
6379
6728
 
6380
6729
  lines.clipEdge(true).duration(0);
6381
- lines2.interactive(false);
6382
- // We don't want any points emitted for the focus chart's scatter graph.
6383
- lines2.pointActive(function(d) { return false; });
6384
-
6385
- x2Axis.orient('bottom').tickPadding(5);
6386
- y2Axis.orient(rightAlignYAxis ? 'right' : 'left');
6387
6730
 
6388
6731
  tooltip.valueFormatter(function(d, i) {
6389
6732
  return yAxis.tickFormat()(d, i);
6390
6733
  }).headerFormatter(function(d, i) {
6391
6734
  return xAxis.tickFormat()(d, i);
6392
6735
  });
6393
-
6736
+
6394
6737
  interactiveLayer.tooltip.valueFormatter(function(d, i) {
6395
6738
  return yAxis.tickFormat()(d, i);
6396
6739
  }).headerFormatter(function(d, i) {
@@ -6424,20 +6767,15 @@ nv.models.lineChart = function() {
6424
6767
  function chart(selection) {
6425
6768
  renderWatch.reset();
6426
6769
  renderWatch.models(lines);
6427
- renderWatch.models(lines2);
6428
6770
  if (showXAxis) renderWatch.models(xAxis);
6429
6771
  if (showYAxis) renderWatch.models(yAxis);
6430
6772
 
6431
- if (focusShowAxisX) renderWatch.models(x2Axis);
6432
- if (focusShowAxisY) renderWatch.models(y2Axis);
6433
6773
  selection.each(function(data) {
6434
6774
  var container = d3.select(this);
6435
6775
  nv.utils.initSVG(container);
6436
6776
  var availableWidth = nv.utils.availableWidth(width, container, margin),
6437
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0),
6438
- availableHeight2 = focusHeight - margin2.top - margin2.bottom;
6439
-
6440
- chart.update = function() {
6777
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
6778
+ chart.update = function() {
6441
6779
  if( duration === 0 ) {
6442
6780
  container.call( chart );
6443
6781
  } else {
@@ -6473,12 +6811,14 @@ nv.models.lineChart = function() {
6473
6811
  container.selectAll('.nv-noData').remove();
6474
6812
  }
6475
6813
 
6814
+ /* Update `main' graph on brush update. */
6815
+ focus.dispatch.on("onBrush", function(extent) {
6816
+ onBrush(extent);
6817
+ });
6476
6818
 
6477
6819
  // Setup Scales
6478
6820
  x = lines.xScale();
6479
6821
  y = lines.yScale();
6480
- x2 = lines2.xScale();
6481
- y2 = lines2.yScale();
6482
6822
 
6483
6823
  // Setup containers and skeleton of chart
6484
6824
  var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);
@@ -6490,17 +6830,11 @@ nv.models.lineChart = function() {
6490
6830
  var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
6491
6831
  focusEnter.append('g').attr('class', 'nv-background').append('rect');
6492
6832
  focusEnter.append('g').attr('class', 'nv-x nv-axis');
6493
- focusEnter.append('g').attr('class', 'nv-y nv-axis');
6494
- focusEnter.append('g').attr('class', 'nv-linesWrap');
6495
- focusEnter.append('g').attr('class', 'nv-interactive');
6496
-
6497
- var contextEnter = gEnter.append('g').attr('class', 'nv-context');
6498
- contextEnter.append('g').attr('class', 'nv-background').append('rect');
6499
- contextEnter.append('g').attr('class', 'nv-x nv-axis');
6500
- contextEnter.append('g').attr('class', 'nv-y nv-axis');
6501
- contextEnter.append('g').attr('class', 'nv-linesWrap');
6502
- contextEnter.append('g').attr('class', 'nv-brushBackground');
6503
- contextEnter.append('g').attr('class', 'nv-x nv-brush');
6833
+ focusEnter.append('g').attr('class', 'nv-y nv-axis');
6834
+ focusEnter.append('g').attr('class', 'nv-linesWrap');
6835
+ focusEnter.append('g').attr('class', 'nv-interactive');
6836
+
6837
+ var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');
6504
6838
 
6505
6839
  // Legend
6506
6840
  if (!showLegend) {
@@ -6514,11 +6848,11 @@ nv.models.lineChart = function() {
6514
6848
 
6515
6849
  if (legendPosition === 'bottom') {
6516
6850
  wrap.select('.nv-legendWrap')
6517
- .attr('transform', 'translate(0,' + (availableHeight1) +')');
6851
+ .attr('transform', 'translate(0,' + availableHeight +')');
6518
6852
  } else if (legendPosition === 'top') {
6519
- if ( margin.top != legend.height()) {
6853
+ if (legend.height() > margin.top) {
6520
6854
  margin.top = legend.height();
6521
- availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0);
6855
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
6522
6856
  }
6523
6857
 
6524
6858
  wrap.select('.nv-legendWrap')
@@ -6537,7 +6871,7 @@ nv.models.lineChart = function() {
6537
6871
  if (useInteractiveGuideline) {
6538
6872
  interactiveLayer
6539
6873
  .width(availableWidth)
6540
- .height(availableHeight1)
6874
+ .height(availableHeight)
6541
6875
  .margin({left:margin.left, top:margin.top})
6542
6876
  .svgContainer(container)
6543
6877
  .xScale(x);
@@ -6546,14 +6880,13 @@ nv.models.lineChart = function() {
6546
6880
 
6547
6881
  g.select('.nv-focus .nv-background rect')
6548
6882
  .attr('width', availableWidth)
6549
- .attr('height', availableHeight1);
6550
-
6883
+ .attr('height', availableHeight);
6884
+
6551
6885
  lines
6552
6886
  .width(availableWidth)
6553
- .height(availableHeight1)
6887
+ .height(availableHeight)
6554
6888
  .color(data.map(function(d,i) {
6555
6889
  return d.color || color(d, i);
6556
-
6557
6890
  }).filter(function(d,i) { return !data[i].disabled; }));
6558
6891
 
6559
6892
  var linesWrap = g.select('.nv-linesWrap')
@@ -6565,14 +6898,13 @@ nv.models.lineChart = function() {
6565
6898
  xAxis
6566
6899
  .scale(x)
6567
6900
  ._ticks(nv.utils.calcTicksX(availableWidth/100, data) )
6568
- .tickSize(-availableHeight1, 0);
6569
-
6901
+ .tickSize(-availableHeight, 0);
6570
6902
  }
6571
6903
 
6572
6904
  if (showYAxis) {
6573
6905
  yAxis
6574
6906
  .scale(y)
6575
- ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) )
6907
+ ._ticks( nv.utils.calcTicksY(availableHeight/36, data) )
6576
6908
  .tickSize( -availableWidth, 0);
6577
6909
  }
6578
6910
 
@@ -6598,104 +6930,28 @@ nv.models.lineChart = function() {
6598
6930
  ;
6599
6931
  }
6600
6932
  }
6601
-
6933
+
6602
6934
  g.select('.nv-focus .nv-x.nv-axis')
6603
- .attr('transform', 'translate(0,' + availableHeight1 + ')');
6935
+ .attr('transform', 'translate(0,' + availableHeight + ')');
6604
6936
 
6605
- if( !focusEnable )
6606
- {
6937
+ //============================================================
6938
+ // Update Focus
6939
+ //============================================================
6940
+ if(!focusEnable) {
6607
6941
  linesWrap.call(lines);
6608
6942
  updateXAxis();
6609
6943
  updateYAxis();
6610
- }
6611
- else
6612
- {
6613
- lines2
6614
- .defined(lines.defined())
6615
- .width(availableWidth)
6616
- .height(availableHeight2)
6617
- .color(data.map(function(d,i) {
6618
- return d.color || color(d, i);
6619
- }).filter(function(d,i) { return !data[i].disabled; }));
6620
-
6621
- g.select('.nv-context')
6622
- .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
6623
- .style('display', focusEnable ? 'initial' : 'none')
6624
- ;
6625
-
6626
- var contextLinesWrap = g.select('.nv-context .nv-linesWrap')
6944
+ } else {
6945
+ focus.width(availableWidth);
6946
+ g.select('.nv-focusWrap')
6947
+ .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')
6627
6948
  .datum(data.filter(function(d) { return !d.disabled; }))
6628
- ;
6629
-
6630
- d3.transition(contextLinesWrap).call(lines2);
6631
-
6632
-
6633
- // Setup Brush
6634
- brush
6635
- .x(x2)
6636
- .on('brush', function() {
6637
- onBrush();
6638
- });
6639
-
6640
- if (brushExtent) brush.extent(brushExtent);
6641
-
6642
- var brushBG = g.select('.nv-brushBackground').selectAll('g')
6643
- .data([brushExtent || brush.extent()]);
6644
-
6645
- var brushBGenter = brushBG.enter()
6646
- .append('g');
6647
-
6648
- brushBGenter.append('rect')
6649
- .attr('class', 'left')
6650
- .attr('x', 0)
6651
- .attr('y', 0)
6652
- .attr('height', availableHeight2);
6653
-
6654
- brushBGenter.append('rect')
6655
- .attr('class', 'right')
6656
- .attr('x', 0)
6657
- .attr('y', 0)
6658
- .attr('height', availableHeight2);
6659
-
6660
- var gBrush = g.select('.nv-x.nv-brush')
6661
- .call(brush);
6662
- gBrush.selectAll('rect')
6663
- .attr('height', availableHeight2);
6664
- gBrush.selectAll('.resize').append('path').attr('d', resizePath);
6665
-
6666
- onBrush();
6667
-
6668
- g.select('.nv-context .nv-background rect')
6669
- .attr('width', availableWidth)
6670
- .attr('height', availableHeight2);
6671
-
6672
- // Setup Secondary (Context) Axes
6673
- if (focusShowAxisX) {
6674
- x2Axis
6675
- .scale(x2)
6676
- ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
6677
- .tickSize(-availableHeight2, 0);
6678
-
6679
- g.select('.nv-context .nv-x.nv-axis')
6680
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
6681
- d3.transition(g.select('.nv-context .nv-x.nv-axis'))
6682
- .call(x2Axis);
6949
+ .call(focus);
6950
+ var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();
6951
+ if(extent !== null){
6952
+ onBrush(extent);
6683
6953
  }
6684
-
6685
- if (focusShowAxisY) {
6686
- y2Axis
6687
- .scale(y2)
6688
- ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) )
6689
- .tickSize( -availableWidth, 0);
6690
-
6691
- d3.transition(g.select('.nv-context .nv-y.nv-axis'))
6692
- .call(y2Axis);
6693
- }
6694
-
6695
- g.select('.nv-context .nv-x.nv-axis')
6696
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
6697
6954
  }
6698
-
6699
6955
  //============================================================
6700
6956
  // Event Handling/Dispatching (in chart's scope)
6701
6957
  //------------------------------------------------------------
@@ -6716,7 +6972,7 @@ nv.models.lineChart = function() {
6716
6972
  return !series.disabled && !series.disableTooltip;
6717
6973
  })
6718
6974
  .forEach(function(series,i) {
6719
- var extent = focusEnable ? (brush.empty() ? x2.domain() : brush.extent()) : x.domain();
6975
+ var extent = focusEnable ? (focus.brush.empty() ? focus.xScale().domain() : focus.brush.extent()) : x.domain();
6720
6976
  var currentValues = series.values.filter(function(d,i) {
6721
6977
  return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
6722
6978
  });
@@ -6752,7 +7008,6 @@ nv.models.lineChart = function() {
6752
7008
  };
6753
7009
 
6754
7010
  interactiveLayer.tooltip
6755
- .chartContainer(chart.container.parentNode)
6756
7011
  .valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)
6757
7012
  .data({
6758
7013
  value: chart.x()( singlePoint,pointIndex ),
@@ -6800,19 +7055,18 @@ nv.models.lineChart = function() {
6800
7055
 
6801
7056
  state.disabled = e.disabled;
6802
7057
  }
6803
-
6804
7058
  chart.update();
6805
7059
  });
6806
7060
 
6807
7061
  //============================================================
6808
7062
  // Functions
6809
7063
  //------------------------------------------------------------
6810
-
7064
+
6811
7065
  // Taken from crossfilter (http://square.github.com/crossfilter/)
6812
7066
  function resizePath(d) {
6813
7067
  var e = +(d == 'e'),
6814
7068
  x = e ? 1 : -1,
6815
- y = availableHeight2 / 3;
7069
+ y = availableHeight / 3;
6816
7070
  return 'M' + (0.5 * x) + ',' + y
6817
7071
  + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
6818
7072
  + 'V' + (2 * y - 6)
@@ -6823,44 +7077,12 @@ nv.models.lineChart = function() {
6823
7077
  + 'M' + (4.5 * x) + ',' + (y + 8)
6824
7078
  + 'V' + (2 * y - 8);
6825
7079
  }
6826
-
6827
-
6828
- function updateBrushBG() {
6829
- if (!brush.empty()) brush.extent(brushExtent);
6830
- brushBG
6831
- .data([brush.empty() ? x2.domain() : brushExtent])
6832
- .each(function(d,i) {
6833
- var leftWidth = x2(d[0]) - x.range()[0],
6834
- rightWidth = availableWidth - x2(d[1]);
6835
- d3.select(this).select('.left')
6836
- .attr('width', leftWidth < 0 ? 0 : leftWidth);
6837
-
6838
- d3.select(this).select('.right')
6839
- .attr('x', x2(d[1]))
6840
- .attr('width', rightWidth < 0 ? 0 : rightWidth);
6841
- });
6842
- }
6843
-
6844
-
6845
- function onBrush() {
6846
- brushExtent = brush.empty() ? null : brush.extent();
6847
- var extent = brush.empty() ? x2.domain() : brush.extent();
6848
-
6849
- //The brush extent cannot be less than one. If it is, don't update the line chart.
6850
- if (Math.abs(extent[0] - extent[1]) <= 1) {
6851
- return;
6852
- }
6853
-
6854
- dispatch.brush({extent: extent, brush: brush});
6855
-
6856
-
6857
- updateBrushBG();
6858
-
7080
+
7081
+ function onBrush(extent) {
6859
7082
  // Update Main (Focus)
6860
7083
  var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
6861
7084
  .datum(
6862
- data
6863
- .filter(function(d) { return !d.disabled; })
7085
+ data.filter(function(d) { return !d.disabled; })
6864
7086
  .map(function(d,i) {
6865
7087
  return {
6866
7088
  key: d.key,
@@ -6874,14 +7096,11 @@ nv.models.lineChart = function() {
6874
7096
  })
6875
7097
  );
6876
7098
  focusLinesWrap.transition().duration(duration).call(lines);
6877
-
6878
-
7099
+
6879
7100
  // Update Main (Focus) Axes
6880
7101
  updateXAxis();
6881
7102
  updateYAxis();
6882
7103
  }
6883
-
6884
-
6885
7104
  });
6886
7105
 
6887
7106
  renderWatch.renderEnd('lineChart immediate');
@@ -6910,12 +7129,12 @@ nv.models.lineChart = function() {
6910
7129
  // expose chart's sub-components
6911
7130
  chart.dispatch = dispatch;
6912
7131
  chart.lines = lines;
6913
- chart.lines2 = lines2;
6914
7132
  chart.legend = legend;
7133
+ chart.focus = focus;
6915
7134
  chart.xAxis = xAxis;
6916
- chart.x2Axis = x2Axis;
7135
+ chart.x2Axis = focus.xAxis
6917
7136
  chart.yAxis = yAxis;
6918
- chart.y2Axis = y2Axis;
7137
+ chart.y2Axis = focus.yAxis
6919
7138
  chart.interactiveLayer = interactiveLayer;
6920
7139
  chart.tooltip = tooltip;
6921
7140
  chart.state = state;
@@ -6930,15 +7149,22 @@ nv.models.lineChart = function() {
6930
7149
  legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
6931
7150
  showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}},
6932
7151
  showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}},
6933
- focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
6934
- focusHeight: {get: function(){return height2;}, set: function(_){focusHeight=_;}},
6935
- focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}},
6936
- focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}},
6937
- brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}},
6938
7152
  defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
6939
7153
  noData: {get: function(){return noData;}, set: function(_){noData=_;}},
7154
+ // Focus options, mostly passed onto focus model.
7155
+ focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
7156
+ focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},
7157
+ focusShowAxisX: {get: function(){return focus.showXAxis();}, set: function(_){focus.showXAxis(_);}},
7158
+ focusShowAxisY: {get: function(){return focus.showYAxis();}, set: function(_){focus.showYAxis(_);}},
7159
+ brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},
6940
7160
 
6941
7161
  // options that require extra logic in the setter
7162
+ focusMargin: {get: function(){return focus.margin}, set: function(_){
7163
+ focus.margin.top = _.top !== undefined ? _.top : focus.margin.top;
7164
+ focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;
7165
+ focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;
7166
+ focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;
7167
+ }},
6942
7168
  margin: {get: function(){return margin;}, set: function(_){
6943
7169
  margin.top = _.top !== undefined ? _.top : margin.top;
6944
7170
  margin.right = _.right !== undefined ? _.right : margin.right;
@@ -6949,41 +7175,35 @@ nv.models.lineChart = function() {
6949
7175
  duration = _;
6950
7176
  renderWatch.reset(duration);
6951
7177
  lines.duration(duration);
7178
+ focus.duration(duration);
6952
7179
  xAxis.duration(duration);
6953
- x2Axis.duration(duration);
6954
7180
  yAxis.duration(duration);
6955
- y2Axis.duration(duration);
6956
- }},
6957
- focusMargin: {get: function(){return margin2;}, set: function(_){
6958
- margin2.top = _.top !== undefined ? _.top : margin2.top;
6959
- margin2.right = _.right !== undefined ? _.right : margin2.right;
6960
- margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom;
6961
- margin2.left = _.left !== undefined ? _.left : margin2.left;
6962
7181
  }},
6963
7182
  color: {get: function(){return color;}, set: function(_){
6964
7183
  color = nv.utils.getColor(_);
6965
7184
  legend.color(color);
6966
7185
  lines.color(color);
7186
+ focus.color(color);
6967
7187
  }},
6968
7188
  interpolate: {get: function(){return lines.interpolate();}, set: function(_){
6969
7189
  lines.interpolate(_);
6970
- lines2.interpolate(_);
7190
+ focus.interpolate(_);
6971
7191
  }},
6972
7192
  xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){
6973
7193
  xAxis.tickFormat(_);
6974
- x2Axis.tickFormat(_);
7194
+ focus.xTickFormat(_);
6975
7195
  }},
6976
7196
  yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){
6977
7197
  yAxis.tickFormat(_);
6978
- y2Axis.tickFormat(_);
7198
+ focus.yTickFormat(_);
6979
7199
  }},
6980
7200
  x: {get: function(){return lines.x();}, set: function(_){
6981
7201
  lines.x(_);
6982
- lines2.x(_);
7202
+ focus.x(_);
6983
7203
  }},
6984
7204
  y: {get: function(){return lines.y();}, set: function(_){
6985
7205
  lines.y(_);
6986
- lines2.y(_);
7206
+ focus.y(_);
6987
7207
  }},
6988
7208
  rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
6989
7209
  rightAlignYAxis = _;
@@ -7006,9 +7226,10 @@ nv.models.lineChart = function() {
7006
7226
 
7007
7227
  nv.models.lineWithFocusChart = function() {
7008
7228
  return nv.models.lineChart()
7009
- .margin({ bottom: 30 })
7229
+ .margin({ bottom: 30 })
7010
7230
  .focusEnable( true );
7011
- };nv.models.linePlusBarChart = function() {
7231
+ };
7232
+ nv.models.linePlusBarChart = function() {
7012
7233
  "use strict";
7013
7234
 
7014
7235
  //============================================================
@@ -7080,13 +7301,13 @@ nv.models.lineWithFocusChart = function() {
7080
7301
  //------------------------------------------------------------
7081
7302
 
7082
7303
  var getBarsAxis = function() {
7083
- return !switchYAxisOrder
7304
+ return switchYAxisOrder
7084
7305
  ? { main: y2Axis, focus: y4Axis }
7085
7306
  : { main: y1Axis, focus: y3Axis }
7086
7307
  }
7087
7308
 
7088
7309
  var getLinesAxis = function() {
7089
- return !switchYAxisOrder
7310
+ return switchYAxisOrder
7090
7311
  ? { main: y1Axis, focus: y3Axis }
7091
7312
  : { main: y2Axis, focus: y4Axis }
7092
7313
  }
@@ -7242,7 +7463,7 @@ nv.models.lineWithFocusChart = function() {
7242
7463
  }))
7243
7464
  .call(legend);
7244
7465
 
7245
- if ( margin.top != legend.height()) {
7466
+ if (legend.height() > margin.top) {
7246
7467
  margin.top = legend.height();
7247
7468
  // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"?
7248
7469
  availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight;
@@ -7460,6 +7681,7 @@ nv.models.lineWithFocusChart = function() {
7460
7681
  return {
7461
7682
  area: d.area,
7462
7683
  fillOpacity: d.fillOpacity,
7684
+ strokeWidth: d.strokeWidth,
7463
7685
  key: d.key,
7464
7686
  values: d.values.filter(function(d,i) {
7465
7687
  return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
@@ -7703,6 +7925,7 @@ nv.models.multiBar = function() {
7703
7925
  , xRange
7704
7926
  , yRange
7705
7927
  , groupSpacing = 0.1
7928
+ , fillOpacity = 0.75
7706
7929
  , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
7707
7930
  ;
7708
7931
 
@@ -7885,7 +8108,7 @@ nv.models.multiBar = function() {
7885
8108
  .style('stroke', function(d,i){ return color(d, i) });
7886
8109
  groups
7887
8110
  .style('stroke-opacity', 1)
7888
- .style('fill-opacity', 0.75);
8111
+ .style('fill-opacity', fillOpacity);
7889
8112
 
7890
8113
  var bars = groups.selectAll('rect.nv-bar')
7891
8114
  .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
@@ -8076,6 +8299,7 @@ nv.models.multiBar = function() {
8076
8299
  id: {get: function(){return id;}, set: function(_){id=_;}},
8077
8300
  hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}},
8078
8301
  groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
8302
+ fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},
8079
8303
 
8080
8304
  // options that require extra logic in the setter
8081
8305
  margin: {get: function(){return margin;}, set: function(_){
@@ -8269,7 +8493,7 @@ nv.models.multiBarChart = function() {
8269
8493
  .datum(data)
8270
8494
  .call(legend);
8271
8495
 
8272
- if ( margin.top != legend.height()) {
8496
+ if (legend.height() > margin.top) {
8273
8497
  margin.top = legend.height();
8274
8498
  availableHeight = nv.utils.availableHeight(height, container, margin);
8275
8499
  }
@@ -8476,7 +8700,6 @@ nv.models.multiBarChart = function() {
8476
8700
  });
8477
8701
 
8478
8702
  interactiveLayer.tooltip
8479
- .chartContainer(that.parentNode)
8480
8703
  .data({
8481
8704
  value: xValue,
8482
8705
  index: pointIndex,
@@ -8611,6 +8834,7 @@ nv.models.multiBarHorizontal = function() {
8611
8834
  , showBarLabels = false
8612
8835
  , valuePadding = 60
8613
8836
  , groupSpacing = 0.1
8837
+ , fillOpacity = 0.75
8614
8838
  , valueFormat = d3.format(',.2f')
8615
8839
  , delay = 1200
8616
8840
  , xDomain
@@ -8718,7 +8942,7 @@ nv.models.multiBarHorizontal = function() {
8718
8942
  .style('stroke', function(d,i){ return color(d, i) });
8719
8943
  groups.watchTransition(renderWatch, 'multibarhorizontal: groups')
8720
8944
  .style('stroke-opacity', 1)
8721
- .style('fill-opacity', .75);
8945
+ .style('fill-opacity', fillOpacity);
8722
8946
 
8723
8947
  var bars = groups.selectAll('g.nv-bar')
8724
8948
  .data(function(d) { return d.values });
@@ -8919,7 +9143,8 @@ nv.models.multiBarHorizontal = function() {
8919
9143
  id: {get: function(){return id;}, set: function(_){id=_;}},
8920
9144
  valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}},
8921
9145
  valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}},
8922
- groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
9146
+ groupSpacing: {get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}},
9147
+ fillOpacity: {get: function(){return fillOpacity;}, set: function(_){fillOpacity=_;}},
8923
9148
 
8924
9149
  // options that require extra logic in the setter
8925
9150
  margin: {get: function(){return margin;}, set: function(_){
@@ -9104,7 +9329,7 @@ nv.models.multiBarHorizontalChart = function() {
9104
9329
  .datum(data)
9105
9330
  .call(legend);
9106
9331
 
9107
- if ( margin.top != legend.height()) {
9332
+ if (legend.height() > margin.top) {
9108
9333
  margin.top = legend.height();
9109
9334
  availableHeight = nv.utils.availableHeight(height, container, margin);
9110
9335
  }
@@ -9460,7 +9685,7 @@ nv.models.multiChart = function() {
9460
9685
  }))
9461
9686
  .call(legend);
9462
9687
 
9463
- if ( margin.top != legend.height()) {
9688
+ if (legend.height() > margin.top) {
9464
9689
  margin.top = legend.height();
9465
9690
  availableHeight = nv.utils.availableHeight(height, container, margin);
9466
9691
  }
@@ -9740,20 +9965,21 @@ nv.models.multiChart = function() {
9740
9965
  });
9741
9966
  });
9742
9967
 
9743
- interactiveLayer.tooltip
9744
- .chartContainer(chart.container.parentNode)
9745
- .headerFormatter(function(d, i) {
9746
- return xAxis.tickFormat()(d, i);
9747
- })
9748
- .valueFormatter(function(d,i) {
9968
+ var defaultValueFormatter = function(d,i) {
9749
9969
  var yAxis = allData[i].yAxis;
9750
- return d === null ? "N/A" : yAxis.tickFormat()(d);
9751
- })
9752
- .data({
9753
- value: chart.x()( singlePoint,pointIndex ),
9754
- index: pointIndex,
9755
- series: allData
9756
- })();
9970
+ return d == null ? "N/A" : yAxis.tickFormat()(d);
9971
+ };
9972
+
9973
+ interactiveLayer.tooltip
9974
+ .headerFormatter(function(d, i) {
9975
+ return xAxis.tickFormat()(d, i);
9976
+ })
9977
+ .valueFormatter(interactiveLayer.tooltip.valueFormatter() || defaultValueFormatter)
9978
+ .data({
9979
+ value: chart.x()( singlePoint,pointIndex ),
9980
+ index: pointIndex,
9981
+ series: allData
9982
+ })();
9757
9983
 
9758
9984
  interactiveLayer.renderGuideLine(pointXLocation);
9759
9985
  });
@@ -10652,7 +10878,7 @@ nv.models.parallelCoordinatesChart = function () {
10652
10878
  ;
10653
10879
 
10654
10880
  //============================================================
10655
-
10881
+
10656
10882
  //============================================================
10657
10883
  // Private Variables
10658
10884
  //------------------------------------------------------------
@@ -10679,18 +10905,18 @@ nv.models.parallelCoordinatesChart = function () {
10679
10905
 
10680
10906
  tooltip.contentGenerator(function(data) {
10681
10907
  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>';
10682
- if(data.series.length !== 0)
10908
+ if(data.series.length !== 0)
10683
10909
  {
10684
10910
  str = str + '<tbody><tr><td height ="10px"></td></tr>';
10685
10911
  data.series.forEach(function(d){
10686
10912
  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>';
10687
- });
10913
+ });
10688
10914
  str = str + '</tbody>';
10689
10915
  }
10690
10916
  str = str + '</table>';
10691
10917
  return str;
10692
10918
  });
10693
-
10919
+
10694
10920
  //============================================================
10695
10921
  // Chart function
10696
10922
  //------------------------------------------------------------
@@ -10743,7 +10969,7 @@ nv.models.parallelCoordinatesChart = function () {
10743
10969
  } else {
10744
10970
  container.selectAll('.nv-noData').remove();
10745
10971
  }
10746
-
10972
+
10747
10973
  //------------------------------------------------------------
10748
10974
  // Setup containers and skeleton of chart
10749
10975
 
@@ -10751,7 +10977,7 @@ nv.models.parallelCoordinatesChart = function () {
10751
10977
  var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinatesChart').append('g');
10752
10978
 
10753
10979
  var g = wrap.select('g');
10754
-
10980
+
10755
10981
  gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap');
10756
10982
  gEnter.append('g').attr('class', 'nv-legendWrap');
10757
10983
 
@@ -10770,7 +10996,7 @@ nv.models.parallelCoordinatesChart = function () {
10770
10996
  .datum(dimensionData.sort(function (a, b) { return a.originalPosition - b.originalPosition; }))
10771
10997
  .call(legend);
10772
10998
 
10773
- if (margin.top != legend.height()) {
10999
+ if (legend.height() > margin.top) {
10774
11000
  margin.top = legend.height();
10775
11001
  availableHeight = nv.utils.availableHeight(height, container, margin);
10776
11002
  }
@@ -10785,12 +11011,12 @@ nv.models.parallelCoordinatesChart = function () {
10785
11011
  .height(availableHeight)
10786
11012
  .dimensionData(dimensionData)
10787
11013
  .displayBrush(displayBrush);
10788
-
11014
+
10789
11015
  var parallelCoordinatesWrap = g.select('.nv-parallelCoordinatesWrap ')
10790
11016
  .datum(data);
10791
11017
 
10792
11018
  parallelCoordinatesWrap.transition().call(parallelCoordinates);
10793
-
11019
+
10794
11020
  //============================================================
10795
11021
  // Event Handling/Dispatching (in chart's scope)
10796
11022
  //------------------------------------------------------------
@@ -10851,7 +11077,7 @@ nv.models.parallelCoordinatesChart = function () {
10851
11077
  key: evt.label,
10852
11078
  color: evt.color,
10853
11079
  series: []
10854
- }
11080
+ }
10855
11081
  if(evt.values){
10856
11082
  Object.keys(evt.values).forEach(function (d) {
10857
11083
  var dim = evt.dimensions.filter(function (dd) {return dd.key === d;})[0];
@@ -10880,7 +11106,7 @@ nv.models.parallelCoordinatesChart = function () {
10880
11106
  //============================================================
10881
11107
  // Expose Public Variables
10882
11108
  //------------------------------------------------------------
10883
-
11109
+
10884
11110
  // expose chart's sub-components
10885
11111
  chart.dispatch = dispatch;
10886
11112
  chart.parallelCoordinates = parallelCoordinates;
@@ -10898,7 +11124,7 @@ nv.models.parallelCoordinatesChart = function () {
10898
11124
  displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } },
10899
11125
  noData: { get: function () { return noData; }, set: function (_) { noData = _; } },
10900
11126
  nanValue: { get: function () { return nanValue; }, set: function (_) { nanValue = _; } },
10901
-
11127
+
10902
11128
  // options that require extra logic in the setter
10903
11129
  margin: {
10904
11130
  get: function () { return margin; },
@@ -10951,6 +11177,7 @@ nv.models.pie = function() {
10951
11177
  , endAngle = false
10952
11178
  , cornerRadius = 0
10953
11179
  , donutRatio = 0.5
11180
+ , duration = 250
10954
11181
  , arcsRadius = []
10955
11182
  , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
10956
11183
  ;
@@ -11090,7 +11317,8 @@ nv.models.pie = function() {
11090
11317
  dispatch.elementMouseover({
11091
11318
  data: d.data,
11092
11319
  index: i,
11093
- color: d3.select(this).style("fill")
11320
+ color: d3.select(this).style("fill"),
11321
+ percent: (d.endAngle - d.startAngle) / (2 * Math.PI)
11094
11322
  });
11095
11323
  });
11096
11324
  ae.on('mouseout', function(d, i) {
@@ -11132,6 +11360,7 @@ nv.models.pie = function() {
11132
11360
 
11133
11361
  slices.select('path')
11134
11362
  .transition()
11363
+ .duration(duration)
11135
11364
  .attr('d', function (d, i) { return arcs[i](d); })
11136
11365
  .attrTween('d', arcTween);
11137
11366
 
@@ -11336,6 +11565,10 @@ nv.models.pie = function() {
11336
11565
  margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
11337
11566
  margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
11338
11567
  }},
11568
+ duration: {get: function(){return duration;}, set: function(_){
11569
+ duration = _;
11570
+ renderWatch.reset(duration);
11571
+ }},
11339
11572
  y: {get: function(){return getY;}, set: function(_){
11340
11573
  getY=d3.functor(_);
11341
11574
  }},
@@ -11364,6 +11597,7 @@ nv.models.pieChart = function() {
11364
11597
  var margin = {top: 30, right: 20, bottom: 20, left: 20}
11365
11598
  , width = null
11366
11599
  , height = null
11600
+ , showTooltipPercent = false
11367
11601
  , showLegend = true
11368
11602
  , legendPosition = "top"
11369
11603
  , color = nv.utils.defaultColor()
@@ -11469,7 +11703,7 @@ nv.models.pieChart = function() {
11469
11703
  .datum(data)
11470
11704
  .call(legend);
11471
11705
 
11472
- if ( margin.top != legend.height()) {
11706
+ if (legend.height() > margin.top) {
11473
11707
  margin.top = legend.height();
11474
11708
  availableHeight = nv.utils.availableHeight(height, container, margin);
11475
11709
  }
@@ -11534,8 +11768,13 @@ nv.models.pieChart = function() {
11534
11768
  evt['series'] = {
11535
11769
  key: chart.x()(evt.data),
11536
11770
  value: chart.y()(evt.data),
11537
- color: evt.color
11771
+ color: evt.color,
11772
+ percent: evt.percent
11538
11773
  };
11774
+ if (!showTooltipPercent) {
11775
+ delete evt.percent;
11776
+ delete evt.series.percent;
11777
+ }
11539
11778
  tooltip.data(evt).hidden(false);
11540
11779
  });
11541
11780
 
@@ -11561,12 +11800,13 @@ nv.models.pieChart = function() {
11561
11800
  // use Object get/set functionality to map between vars and chart functions
11562
11801
  chart._options = Object.create({}, {
11563
11802
  // simple options, just get/set the necessary values
11564
- width: {get: function(){return width;}, set: function(_){width=_;}},
11565
- height: {get: function(){return height;}, set: function(_){height=_;}},
11566
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
11567
- showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
11568
- legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
11569
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
11803
+ width: {get: function(){return width;}, set: function(_){width=_;}},
11804
+ height: {get: function(){return height;}, set: function(_){height=_;}},
11805
+ noData: {get: function(){return noData;}, set: function(_){noData=_;}},
11806
+ showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},
11807
+ showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}},
11808
+ legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}},
11809
+ defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
11570
11810
 
11571
11811
  // options that require extra logic in the setter
11572
11812
  color: {get: function(){return color;}, set: function(_){
@@ -11577,6 +11817,7 @@ nv.models.pieChart = function() {
11577
11817
  duration: {get: function(){return duration;}, set: function(_){
11578
11818
  duration = _;
11579
11819
  renderWatch.reset(duration);
11820
+ pie.duration(duration);
11580
11821
  }},
11581
11822
  margin: {get: function(){return margin;}, set: function(_){
11582
11823
  margin.top = _.top !== undefined ? _.top : margin.top;
@@ -11926,14 +12167,16 @@ nv.models.scatter = function() {
11926
12167
  if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
11927
12168
  var series = data[d.series],
11928
12169
  point = series.values[i];
11929
-
12170
+ var element = this;
11930
12171
  dispatch.elementClick({
11931
12172
  point: point,
11932
12173
  series: series,
11933
12174
  pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page
11934
12175
  relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
11935
12176
  seriesIndex: d.series,
11936
- pointIndex: i
12177
+ pointIndex: i,
12178
+ event: d3.event,
12179
+ element: element
11937
12180
  });
11938
12181
  })
11939
12182
  .on('dblclick', function(d,i) {
@@ -12377,7 +12620,7 @@ nv.models.scatterChart = function() {
12377
12620
  .datum(data)
12378
12621
  .call(legend);
12379
12622
 
12380
- if ( margin.top != legend.height()) {
12623
+ if (legend.height() > margin.top) {
12381
12624
  margin.top = legend.height();
12382
12625
  availableHeight = nv.utils.availableHeight(height, container, margin);
12383
12626
  }
@@ -13304,6 +13547,7 @@ nv.models.stackedAreaChart = function() {
13304
13547
  , controls = nv.models.legend()
13305
13548
  , interactiveLayer = nv.interactiveGuideline()
13306
13549
  , tooltip = nv.models.tooltip()
13550
+ , focus = nv.models.focus(nv.models.stackedArea())
13307
13551
  ;
13308
13552
 
13309
13553
  var margin = {top: 30, right: 25, bottom: 50, left: 60}
@@ -13315,6 +13559,7 @@ nv.models.stackedAreaChart = function() {
13315
13559
  , showXAxis = true
13316
13560
  , showYAxis = true
13317
13561
  , rightAlignYAxis = false
13562
+ , focusEnable = false
13318
13563
  , useInteractiveGuideline = false
13319
13564
  , showTotalInTooltip = true
13320
13565
  , totalLabel = 'TOTAL'
@@ -13347,7 +13592,7 @@ nv.models.stackedAreaChart = function() {
13347
13592
  return xAxis.tickFormat()(d, i);
13348
13593
  })
13349
13594
  .valueFormatter(function(d, i) {
13350
- return yAxis.tickFormat()(d, i);
13595
+ return d == null ? "N/A" : yAxis.tickFormat()(d, i);
13351
13596
  });
13352
13597
 
13353
13598
  var oldYTickFormat = null,
@@ -13396,7 +13641,7 @@ nv.models.stackedAreaChart = function() {
13396
13641
  nv.utils.initSVG(container);
13397
13642
 
13398
13643
  var availableWidth = nv.utils.availableWidth(width, container, margin),
13399
- availableHeight = nv.utils.availableHeight(height, container, margin);
13644
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
13400
13645
 
13401
13646
  chart.update = function() { container.transition().duration(duration).call(chart); };
13402
13647
  chart.container = this;
@@ -13427,7 +13672,6 @@ nv.models.stackedAreaChart = function() {
13427
13672
  } else {
13428
13673
  container.selectAll('.nv-noData').remove();
13429
13674
  }
13430
-
13431
13675
  // Setup Scales
13432
13676
  x = stacked.xScale();
13433
13677
  y = stacked.yScale();
@@ -13437,15 +13681,19 @@ nv.models.stackedAreaChart = function() {
13437
13681
  var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');
13438
13682
  var g = wrap.select('g');
13439
13683
 
13440
- gEnter.append("rect").style("opacity",0);
13441
- gEnter.append('g').attr('class', 'nv-x nv-axis');
13442
- gEnter.append('g').attr('class', 'nv-y nv-axis');
13443
- gEnter.append('g').attr('class', 'nv-stackedWrap');
13444
13684
  gEnter.append('g').attr('class', 'nv-legendWrap');
13445
13685
  gEnter.append('g').attr('class', 'nv-controlsWrap');
13446
- gEnter.append('g').attr('class', 'nv-interactive');
13447
13686
 
13448
- g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
13687
+ var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
13688
+ focusEnter.append('g').attr('class', 'nv-background').append('rect');
13689
+ focusEnter.append('g').attr('class', 'nv-x nv-axis');
13690
+ focusEnter.append('g').attr('class', 'nv-y nv-axis');
13691
+ focusEnter.append('g').attr('class', 'nv-stackedWrap');
13692
+ focusEnter.append('g').attr('class', 'nv-interactive');
13693
+
13694
+ // g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
13695
+
13696
+ var contextEnter = gEnter.append('g').attr('class', 'nv-focusWrap');
13449
13697
 
13450
13698
  // Legend
13451
13699
  if (!showLegend) {
@@ -13456,9 +13704,9 @@ nv.models.stackedAreaChart = function() {
13456
13704
  legend.width(legendWidth);
13457
13705
  g.select('.nv-legendWrap').datum(data).call(legend);
13458
13706
 
13459
- if ( margin.top != legend.height()) {
13707
+ if (legend.height() > margin.top) {
13460
13708
  margin.top = legend.height();
13461
- availableHeight = nv.utils.availableHeight(height, container, margin);
13709
+ availableHeight = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focus.height() : 0);
13462
13710
  }
13463
13711
 
13464
13712
  g.select('.nv-legendWrap')
@@ -13509,7 +13757,7 @@ nv.models.stackedAreaChart = function() {
13509
13757
  .datum(controlsData)
13510
13758
  .call(controls);
13511
13759
 
13512
- if ( margin.top != Math.max(controls.height(), legend.height()) ) {
13760
+ if (Math.max(controls.height(), legend.height()) > margin.top) {
13513
13761
  margin.top = Math.max(controls.height(), legend.height());
13514
13762
  availableHeight = nv.utils.availableHeight(height, container, margin);
13515
13763
  }
@@ -13536,27 +13784,25 @@ nv.models.stackedAreaChart = function() {
13536
13784
  wrap.select(".nv-interactive").call(interactiveLayer);
13537
13785
  }
13538
13786
 
13787
+ g.select('.nv-focus .nv-background rect')
13788
+ .attr('width', availableWidth)
13789
+ .attr('height', availableHeight);
13790
+
13539
13791
  stacked
13540
13792
  .width(availableWidth)
13541
- .height(availableHeight);
13542
-
13543
- var stackedWrap = g.select('.nv-stackedWrap')
13544
- .datum(data);
13793
+ .height(availableHeight)
13794
+ .color(data.map(function(d,i) {
13795
+ return d.color || color(d, i);
13796
+ }).filter(function(d,i) { return !data[i].disabled; }));
13545
13797
 
13546
- stackedWrap.transition().call(stacked);
13798
+ var stackedWrap = g.select('.nv-focus .nv-stackedWrap')
13799
+ .datum(data.filter(function(d) { return !d.disabled; }));
13547
13800
 
13548
13801
  // Setup Axes
13549
13802
  if (showXAxis) {
13550
13803
  xAxis.scale(x)
13551
13804
  ._ticks( nv.utils.calcTicksX(availableWidth/100, data) )
13552
13805
  .tickSize( -availableHeight, 0);
13553
-
13554
- g.select('.nv-x.nv-axis')
13555
- .attr('transform', 'translate(0,' + availableHeight + ')');
13556
-
13557
- g.select('.nv-x.nv-axis')
13558
- .transition().duration(0)
13559
- .call(xAxis);
13560
13806
  }
13561
13807
 
13562
13808
  if (showYAxis) {
@@ -13570,7 +13816,24 @@ nv.models.stackedAreaChart = function() {
13570
13816
  yAxis.scale(y)
13571
13817
  ._ticks(ticks)
13572
13818
  .tickSize(-availableWidth, 0);
13819
+ }
13820
+
13821
+ //============================================================
13822
+ // Update Axes
13823
+ //============================================================
13824
+ function updateXAxis() {
13825
+ if(showXAxis) {
13826
+ g.select('.nv-focus .nv-x.nv-axis')
13827
+ .attr('transform', 'translate(0,' + availableHeight + ')')
13828
+ .transition()
13829
+ .duration(duration)
13830
+ .call(xAxis)
13831
+ ;
13832
+ }
13833
+ }
13573
13834
 
13835
+ function updateYAxis() {
13836
+ if(showYAxis) {
13574
13837
  if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') {
13575
13838
  var currentFormat = yAxis.tickFormat();
13576
13839
 
@@ -13587,9 +13850,29 @@ nv.models.stackedAreaChart = function() {
13587
13850
  }
13588
13851
  }
13589
13852
 
13590
- g.select('.nv-y.nv-axis')
13853
+ g.select('.nv-focus .nv-y.nv-axis')
13591
13854
  .transition().duration(0)
13592
13855
  .call(yAxis);
13856
+ }
13857
+ }
13858
+
13859
+ //============================================================
13860
+ // Update Focus
13861
+ //============================================================
13862
+ if(!focusEnable) {
13863
+ stackedWrap.transition().call(stacked);
13864
+ updateXAxis();
13865
+ updateYAxis();
13866
+ } else {
13867
+ focus.width(availableWidth);
13868
+ g.select('.nv-focusWrap')
13869
+ .attr('transform', 'translate(0,' + ( availableHeight + margin.bottom + focus.margin().top) + ')')
13870
+ .datum(data.filter(function(d) { return !d.disabled; }))
13871
+ .call(focus);
13872
+ var extent = focus.brush.empty() ? focus.xDomain() : focus.brush.extent();
13873
+ if(extent !== null){
13874
+ onBrush(extent);
13875
+ }
13593
13876
  }
13594
13877
 
13595
13878
  //============================================================
@@ -13639,7 +13922,7 @@ nv.models.stackedAreaChart = function() {
13639
13922
 
13640
13923
  interactiveLayer.dispatch.on('elementMousemove', function(e) {
13641
13924
  stacked.clearHighlights();
13642
- var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0;
13925
+ var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0, allNullValues = true;
13643
13926
  data
13644
13927
  .filter(function(series, i) {
13645
13928
  series.seriesIndex = i;
@@ -13665,8 +13948,9 @@ nv.models.stackedAreaChart = function() {
13665
13948
  point: point
13666
13949
  });
13667
13950
 
13668
- if (showTotalInTooltip && stacked.style() != 'expand') {
13951
+ if (showTotalInTooltip && stacked.style() != 'expand' && tooltipValue != null) {
13669
13952
  valueSum += tooltipValue;
13953
+ allNullValues = false;
13670
13954
  };
13671
13955
  });
13672
13956
 
@@ -13694,7 +13978,7 @@ nv.models.stackedAreaChart = function() {
13694
13978
  }
13695
13979
 
13696
13980
  //If we are not in 'expand' mode, add a 'Total' row to the tooltip.
13697
- if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2) {
13981
+ if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2 && !allNullValues) {
13698
13982
  allData.push({
13699
13983
  key: totalLabel,
13700
13984
  value: valueSum,
@@ -13721,7 +14005,6 @@ nv.models.stackedAreaChart = function() {
13721
14005
  }
13722
14006
 
13723
14007
  interactiveLayer.tooltip
13724
- .chartContainer(that.parentNode)
13725
14008
  .valueFormatter(valueFormatter)
13726
14009
  .data(
13727
14010
  {
@@ -13738,6 +14021,11 @@ nv.models.stackedAreaChart = function() {
13738
14021
  stacked.clearHighlights();
13739
14022
  });
13740
14023
 
14024
+ /* Update `main' graph on brush update. */
14025
+ focus.dispatch.on("onBrush", function(extent) {
14026
+ onBrush(extent);
14027
+ });
14028
+
13741
14029
  // Update chart from a state object passed to event handler
13742
14030
  dispatch.on('changeState', function(e) {
13743
14031
 
@@ -13757,6 +14045,34 @@ nv.models.stackedAreaChart = function() {
13757
14045
  chart.update();
13758
14046
  });
13759
14047
 
14048
+ //============================================================
14049
+ // Functions
14050
+ //------------------------------------------------------------
14051
+
14052
+ function onBrush(extent) {
14053
+ // Update Main (Focus)
14054
+ var stackedWrap = g.select('.nv-focus .nv-stackedWrap')
14055
+ .datum(
14056
+ data.filter(function(d) { return !d.disabled; })
14057
+ .map(function(d,i) {
14058
+ return {
14059
+ key: d.key,
14060
+ area: d.area,
14061
+ classed: d.classed,
14062
+ values: d.values.filter(function(d,i) {
14063
+ return stacked.x()(d,i) >= extent[0] && stacked.x()(d,i) <= extent[1];
14064
+ }),
14065
+ disableTooltip: d.disableTooltip
14066
+ };
14067
+ })
14068
+ );
14069
+ stackedWrap.transition().duration(duration).call(stacked);
14070
+
14071
+ // Update Main (Focus) Axes
14072
+ updateXAxis();
14073
+ updateYAxis();
14074
+ }
14075
+
13760
14076
  });
13761
14077
 
13762
14078
  renderWatch.renderEnd('stacked Area chart immediate');
@@ -13776,7 +14092,6 @@ nv.models.stackedAreaChart = function() {
13776
14092
  stacked.dispatch.on('elementMouseout.tooltip', function(evt) {
13777
14093
  tooltip.hidden(true)
13778
14094
  });
13779
-
13780
14095
  //============================================================
13781
14096
  // Expose Public Variables
13782
14097
  //------------------------------------------------------------
@@ -13787,9 +14102,12 @@ nv.models.stackedAreaChart = function() {
13787
14102
  chart.legend = legend;
13788
14103
  chart.controls = controls;
13789
14104
  chart.xAxis = xAxis;
14105
+ chart.x2Axis = focus.xAxis;
13790
14106
  chart.yAxis = yAxis;
14107
+ chart.y2Axis = focus.yAxis;
13791
14108
  chart.interactiveLayer = interactiveLayer;
13792
14109
  chart.tooltip = tooltip;
14110
+ chart.focus = focus;
13793
14111
 
13794
14112
  chart.dispatch = dispatch;
13795
14113
  chart.options = nv.utils.optionsFunc.bind(chart);
@@ -13808,6 +14126,9 @@ nv.models.stackedAreaChart = function() {
13808
14126
  controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}},
13809
14127
  showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}},
13810
14128
  totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}},
14129
+ focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}},
14130
+ focusHeight: {get: function(){return focus.height();}, set: function(_){focus.height(_);}},
14131
+ brushExtent: {get: function(){return focus.brushExtent();}, set: function(_){focus.brushExtent(_);}},
13811
14132
 
13812
14133
  // options that require extra logic in the setter
13813
14134
  margin: {get: function(){return margin;}, set: function(_){
@@ -13816,6 +14137,12 @@ nv.models.stackedAreaChart = function() {
13816
14137
  margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
13817
14138
  margin.left = _.left !== undefined ? _.left : margin.left;
13818
14139
  }},
14140
+ focusMargin: {get: function(){return focus.margin}, set: function(_){
14141
+ focus.margin.top = _.top !== undefined ? _.top : focus.margin.top;
14142
+ focus.margin.right = _.right !== undefined ? _.right : focus.margin.right;
14143
+ focus.margin.bottom = _.bottom !== undefined ? _.bottom : focus.margin.bottom;
14144
+ focus.margin.left = _.left !== undefined ? _.left : focus.margin.left;
14145
+ }},
13819
14146
  duration: {get: function(){return duration;}, set: function(_){
13820
14147
  duration = _;
13821
14148
  renderWatch.reset(duration);
@@ -13827,6 +14154,15 @@ nv.models.stackedAreaChart = function() {
13827
14154
  color = nv.utils.getColor(_);
13828
14155
  legend.color(color);
13829
14156
  stacked.color(color);
14157
+ focus.color(color);
14158
+ }},
14159
+ x: {get: function(){return stacked.x();}, set: function(_){
14160
+ stacked.x(_);
14161
+ focus.x(_);
14162
+ }},
14163
+ y: {get: function(){return stacked.y();}, set: function(_){
14164
+ stacked.y(_);
14165
+ focus.y(_);
13830
14166
  }},
13831
14167
  rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){
13832
14168
  rightAlignYAxis = _;
@@ -13845,6 +14181,12 @@ nv.models.stackedAreaChart = function() {
13845
14181
 
13846
14182
  return chart;
13847
14183
  };
14184
+
14185
+ nv.models.stackedAreaWithFocusChart = function() {
14186
+ return nv.models.stackedAreaChart()
14187
+ .margin({ bottom: 30 })
14188
+ .focusEnable( true );
14189
+ };
13848
14190
  // based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad
13849
14191
  nv.models.sunburst = function() {
13850
14192
  "use strict";
@@ -13905,6 +14247,12 @@ nv.models.sunburst = function() {
13905
14247
  return centerAngle;
13906
14248
  }
13907
14249
 
14250
+ function computeNodePercentage(d) {
14251
+ var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));
14252
+ var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
14253
+ return (endAngle - startAngle) / (2 * Math.PI);
14254
+ }
14255
+
13908
14256
  function labelThresholdMatched(d) {
13909
14257
  var startAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x)));
13910
14258
  var endAngle = Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
@@ -14054,7 +14402,9 @@ nv.models.sunburst = function() {
14054
14402
  if( !wrap[0][0] ) {
14055
14403
  wrap = container.append('g')
14056
14404
  .attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id)
14057
- .attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
14405
+ .attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');
14406
+ } else {
14407
+ wrap.attr('transform', 'translate(' + ((availableWidth / 2) + margin.left + margin.right) + ',' + ((availableHeight / 2) + margin.top + margin.bottom) + ')');
14058
14408
  }
14059
14409
 
14060
14410
  container.on('click', function (d, i) {
@@ -14099,7 +14449,8 @@ nv.models.sunburst = function() {
14099
14449
  d3.select(this).classed('hover', true).style('opacity', 0.8);
14100
14450
  dispatch.elementMouseover({
14101
14451
  data: d,
14102
- color: d3.select(this).style("fill")
14452
+ color: d3.select(this).style("fill"),
14453
+ percent: computeNodePercentage(d)
14103
14454
  });
14104
14455
  })
14105
14456
  .on('mouseout', function(d,i){
@@ -14229,6 +14580,7 @@ nv.models.sunburstChart = function() {
14229
14580
  , width = null
14230
14581
  , height = null
14231
14582
  , color = nv.utils.defaultColor()
14583
+ , showTooltipPercent = false
14232
14584
  , id = Math.round(Math.random() * 100000)
14233
14585
  , defaultState = null
14234
14586
  , noData = null
@@ -14280,7 +14632,7 @@ nv.models.sunburstChart = function() {
14280
14632
  container.selectAll('.nv-noData').remove();
14281
14633
  }
14282
14634
 
14283
- sunburst.width(availableWidth).height(availableHeight);
14635
+ sunburst.width(availableWidth).height(availableHeight).margin(margin);
14284
14636
  container.call(sunburst);
14285
14637
  });
14286
14638
 
@@ -14296,8 +14648,13 @@ nv.models.sunburstChart = function() {
14296
14648
  evt.series = {
14297
14649
  key: evt.data.name,
14298
14650
  value: (evt.data.value || evt.data.size),
14299
- color: evt.color
14651
+ color: evt.color,
14652
+ percent: evt.percent
14300
14653
  };
14654
+ if (!showTooltipPercent) {
14655
+ delete evt.percent;
14656
+ delete evt.series.percent;
14657
+ }
14301
14658
  tooltip.data(evt).hidden(false);
14302
14659
  });
14303
14660
 
@@ -14322,8 +14679,9 @@ nv.models.sunburstChart = function() {
14322
14679
  // use Object get/set functionality to map between vars and chart functions
14323
14680
  chart._options = Object.create({}, {
14324
14681
  // simple options, just get/set the necessary values
14325
- noData: {get: function(){return noData;}, set: function(_){noData=_;}},
14326
- defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
14682
+ noData: {get: function(){return noData;}, set: function(_){noData=_;}},
14683
+ defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}},
14684
+ showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}},
14327
14685
 
14328
14686
  // options that require extra logic in the setter
14329
14687
  color: {get: function(){return color;}, set: function(_){
@@ -14340,6 +14698,7 @@ nv.models.sunburstChart = function() {
14340
14698
  margin.right = _.right !== undefined ? _.right : margin.right;
14341
14699
  margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom;
14342
14700
  margin.left = _.left !== undefined ? _.left : margin.left;
14701
+ sunburst.margin(margin);
14343
14702
  }}
14344
14703
  });
14345
14704
  nv.utils.inheritOptions(chart, sunburst);
@@ -14348,5 +14707,5 @@ nv.models.sunburstChart = function() {
14348
14707
 
14349
14708
  };
14350
14709
 
14351
- nv.version = "1.8.3";
14710
+ nv.version = "1.8.4";
14352
14711
  })();