novus-nvd3-rails 1.8.3 → 1.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  })();