瀏覽代碼

HUE-8074 [charts] Better handling of more than a few legend items

jdesjean 7 年之前
父節點
當前提交
dc7f14d

+ 36 - 5
desktop/core/src/desktop/static/desktop/js/ko.charts.js

@@ -279,7 +279,9 @@
       var _chart = $(element).data("chart");
       if (_chart) {
         window.setTimeout(function () {
-          _chart.multibar.stacked(typeof _options.stacked != "undefined" ? _options.stacked : false);
+          if (_chart.multibar) {
+            _chart.multibar.stacked(typeof _options.stacked != "undefined" ? _options.stacked : false);
+          }
           var enableSelection = true;
           if (typeof _options.enableSelection !== 'undefined') {
             enableSelection = _options.enableSelection;
@@ -767,7 +769,7 @@
         _chart.yAxis
             .tickFormat(d3v3.format(",0f"));
 
-        var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).append("svg");
+        var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).insert("svg", ":first-child");
         _d3.datum(_datum)
             .transition().duration(150)
             .each("end", function () {
@@ -795,7 +797,15 @@
 
         return _chart;
       }, function () {
-        var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).append("svg");
+        if ($(element).find("svg").length > 0) {
+          _d3 = d3v3.select($(element).find("svg")[0]);
+          if ($(element).find("svg").length < 2) {
+            addLegend(element);
+          }
+        } else {
+          _d3 = d3v3.select($(element)[0]).append("svg");
+          addLegend(element);
+        }
         _d3.selectAll(".nv-line").on("click",
             function (d, i) {
               if (typeof options.onClick != "undefined") {
@@ -807,6 +817,18 @@
     }
   }
 
+  function addLegend(element) {
+    d3v3.select($(element)[0])
+      .append("div")
+        .style("position", "absolute")
+        .style("overflow", "auto")
+        .style("top", "0px")
+        .style("right", "0px")
+        .style("width", "175px")
+        .style("height", "100%")
+      .append("svg");
+  }
+
   function barChartBuilder(element, options, isTimeline) {
     var _datum = options.transformer(options.datum);
     $(element).height(300);
@@ -943,7 +965,7 @@
 
       $(element).data("chart", _chart);
 
-      var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).append("svg");
+      var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).insert("svg",":first-child");
       _d3.datum(_datum)
         .transition().duration(150)
         .each("end", function () {
@@ -994,7 +1016,16 @@
 
       return _chart;
     }, function () {
-      var _d3 = ($(element).find("svg").length > 0) ? d3v3.select($(element).find("svg")[0]) : d3v3.select($(element)[0]).append("svg");
+      var _d3;
+      if ($(element).find("svg").length > 0) {
+        _d3 = d3v3.select($(element).find("svg")[0]);
+        if ($(element).find("svg").length < 2) {
+          addLegend(element);
+        }
+      } else {
+        _d3 = d3v3.select($(element)[0]).append("svg");
+        addLegend(element);
+      }
       _d3.selectAll(".nv-bar").on("click",
         function (d, i) {
           if (typeof options.onClick != "undefined") {

+ 26 - 18
desktop/core/src/desktop/static/desktop/js/nv.d3.lineWithBrushChart.js

@@ -57,6 +57,7 @@ nv.models.lineWithBrushChart = function() {
     , noData = 'No Data Available.'
     , dispatch = d3v3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'brush')
     , controlWidth = function() { return showControls ? (selectionHidden ? 240 : 300) : 0 }
+    , legendWidth = 175
     , transitionDuration = 250
     , extent
     , brushExtent = null
@@ -104,6 +105,7 @@ nv.models.lineWithBrushChart = function() {
 
       var availableWidth = (width  || parseInt(container.style('width')) || 960)
                              - margin.left - margin.right,
+          availableChartWidth = Math.max(availableWidth - legendWidth, 0),
           availableHeight = (height || parseInt(container.style('height')) || 400)
                              - margin.top - margin.bottom;
 
@@ -178,31 +180,37 @@ nv.models.lineWithBrushChart = function() {
       gEnter.append('g').attr('class', 'nv-x nv-axis');
       gEnter.append('g').attr('class', 'nv-y nv-axis');
       gEnter.append('g').attr('class', 'nv-linesWrap');
-      gEnter.append('g').attr('class', 'nv-legendWrap');
+      // We put the legend in an another SVG to support scrolling
+      var legendDiv = d3.select(container.node().parentNode).select('div');
+      var legendSvg = legendDiv.select('svg').size() === 0 ? legendDiv.append('svg') : legendDiv.select('svg');
+      legendSvg.style('height', (data.length * 20 + 6) + 'px').selectAll('g').remove();
+      var legendG = legendSvg.append('g').attr('class', 'nvd3 nv-wrap nv-legendWrap');
       gEnter.append('g').attr('class', 'nv-interactive');
       gEnter.append('g').attr('class', 'nv-controlsWrap');
 
       g.select("rect")
-        .attr("width",availableWidth)
+        .attr("width",availableChartWidth)
         .attr("height",(availableHeight > 0) ? availableHeight : 0);
       //------------------------------------------------------------
       // Legend
 
       if (showLegend) {
-        legend.width(availableWidth - controlWidth());
+        legend.width(legendWidth);
+        legend.height(availableHeight);
+        legend.rightAlign(false);
+        legend.margin({top: 5, right: 0, left: 10, bottom: 0});
 
-        g.select('.nv-legendWrap')
+        try {
+          legendG
             .datum(data)
-            .call(legend);
-
-        if ( margin.top != legend.height()) {
-          margin.top = legend.height();
-          availableHeight = (height || parseInt(container.style('height')) || 400)
-                             - margin.top - margin.bottom;
+            .call(legend)
+          .selectAll('text')
+          .append('title')
+          .text(function(d){
+            return d.key;
+          });
         }
-
-        wrap.select('.nv-legendWrap')
-            .attr('transform', 'translate(0,' + (-margin.top) +')')
+        catch (e){}
       }
 
       if (showControls) {
@@ -225,7 +233,7 @@ nv.models.lineWithBrushChart = function() {
 
       if (rightAlignYAxis) {
           g.select(".nv-y.nv-axis")
-              .attr("transform", "translate(" + availableWidth + ",0)");
+              .attr("transform", "translate(" + availableChartWidth + ",0)");
       }
 
       //------------------------------------------------------------
@@ -236,7 +244,7 @@ nv.models.lineWithBrushChart = function() {
       //Set up interactive layer
       if (useInteractiveGuideline) {
         interactiveLayer
-           .width(availableWidth)
+           .width(availableChartWidth)
            .height(availableHeight)
            .margin({left:margin.left, top:margin.top})
            .svgContainer(container)
@@ -246,7 +254,7 @@ nv.models.lineWithBrushChart = function() {
 
 
       lines
-        .width(availableWidth)
+        .width(availableChartWidth)
         .height(availableHeight)
         .color(data.map(function(d,i) {
           return d.color || color(d, i);
@@ -315,7 +323,7 @@ nv.models.lineWithBrushChart = function() {
       if (showXAxis) {
         xAxis
           .scale(x)
-          .ticks( availableWidth / 100 )
+          .ticks( availableChartWidth / 100 )
           .tickSize(-availableHeight, 0);
 
         g.select('.nv-x.nv-axis')
@@ -329,7 +337,7 @@ nv.models.lineWithBrushChart = function() {
         yAxis
           .scale(y)
           .ticks( availableHeight / 36 )
-          .tickSize( -availableWidth, 0);
+          .tickSize( -availableChartWidth, 0);
 
         g.select('.nv-y.nv-axis')
             .transition()

+ 25 - 21
desktop/core/src/desktop/static/desktop/js/nv.d3.multiBarWithBrushChart.js

@@ -59,6 +59,7 @@ nv.models.multiBarWithBrushChart = function() {
     , noData = "No Data Available."
     , dispatch = d3v3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'brush')
     , controlWidth = function() { return showControls ? (selectionHidden ? 240 : 300) : 0 }
+    , legendWidth = 175
     , transitionDuration = 250
     , extent
     , brushExtent = null
@@ -113,6 +114,7 @@ nv.models.multiBarWithBrushChart = function() {
 
       var availableWidth = (width  || parseInt(container.style('width')) || 960)
                              - margin.left - margin.right,
+          availableChartWidth = Math.max(availableWidth - legendWidth, 0),
           availableHeight = (height || parseInt(container.style('height')) || 400)
                              - margin.top - margin.bottom;
 
@@ -191,7 +193,11 @@ nv.models.multiBarWithBrushChart = function() {
       gEnter.append('g').attr('class', 'nv-x nv-axis');
       gEnter.append('g').attr('class', 'nv-y nv-axis');
       gEnter.append('g').attr('class', 'nv-barsWrap');
-      gEnter.append('g').attr('class', 'nv-legendWrap');
+      // We put the legend in an another SVG to support scrolling
+      var legendDiv = d3.select(container.node().parentNode).select('div');
+      var legendSvg = legendDiv.select('svg').size() === 0 ? legendDiv.append('svg') : legendDiv.select('svg');
+      legendSvg.style('height', (data.length * 20 + 6) + 'px').selectAll('g').remove();
+      var legendG = legendSvg.append('g').attr('class', 'nvd3 nv-wrap nv-legendWrap');
       gEnter.append('g').attr('class', 'nv-controlsWrap');
 
 
@@ -202,28 +208,26 @@ nv.models.multiBarWithBrushChart = function() {
       // Legend
 
       if (showLegend) {
-        legend.width(availableWidth - controlWidth());
-
+        legend.width(legendWidth);
+        legend.height(availableHeight);
+        legend.rightAlign(false);
+        legend.margin({top: 5, right: 0, left: 10, bottom: 0});
         if (multibar.barColor())
           data.forEach(function(series,i) {
             series.color = d3v3.rgb('#ccc').darker(i * 1.5).toString();
-          })
+          });
 
         try {
-          g.select('.nv-legendWrap')
-              .datum(data)
-              .call(legend);
+          legendG
+            .datum(data)
+            .call(legend)
+          .selectAll('text')
+          .append('title')
+          .text(function(d){
+            return d.key;
+          });
         }
         catch (e){}
-
-        if ( margin.top != legend.height()) {
-          margin.top = legend.height();
-          availableHeight = (height || parseInt(container.style('height')) || 400)
-                             - margin.top - margin.bottom;
-        }
-
-        g.select('.nv-legendWrap')
-            .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
       }
 
       //------------------------------------------------------------
@@ -256,7 +260,7 @@ nv.models.multiBarWithBrushChart = function() {
 
       if (rightAlignYAxis) {
           g.select(".nv-y.nv-axis")
-              .attr("transform", "translate(" + availableWidth + ",0)");
+              .attr("transform", "translate(" + availableChartWidth + ",0)");
       }
 
       //------------------------------------------------------------
@@ -264,7 +268,7 @@ nv.models.multiBarWithBrushChart = function() {
 
       multibar
         .disabled(data.map(function(series) { return series.disabled }))
-        .width(availableWidth)
+        .width(availableChartWidth)
         .height(availableHeight)
         .color(data.map(function(d,i) {
           return d.color || color(d, i);
@@ -339,7 +343,7 @@ nv.models.multiBarWithBrushChart = function() {
       if (showXAxis) {
           xAxis
             .scale(x)
-            .ticks( availableWidth / 100 )
+            .ticks( availableChartWidth / 100 )
             .tickSize(-availableHeight, 0);
 
           g.select('.nv-x.nv-axis')
@@ -386,7 +390,7 @@ nv.models.multiBarWithBrushChart = function() {
           if (reduceXTicks)
             xTicks
               .filter(function(d,i) {
-                  return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;
+                  return i % Math.ceil(data[0].values.length / (availableChartWidth / 100)) !== 0;
                 })
               .selectAll('text, line')
               .style('opacity', 0);
@@ -406,7 +410,7 @@ nv.models.multiBarWithBrushChart = function() {
           yAxis
             .scale(y)
             .ticks( availableHeight / 36 )
-            .tickSize( -availableWidth, 0);
+            .tickSize( -availableChartWidth, 0);
 
           g.select('.nv-y.nv-axis').transition()
               .call(yAxis);