D3 tooltips

by JaelB

HTML

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.6/dc.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.6/dc.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

  <body>
    <div id='stack'></div>
    <div id='line'></div>
  </body>

</html>

CSS

div.tooltip {
   position: absolute;
   text-align: center;
   width: 220px;
   height: 125px;
   padding: 2px;
   font: 12px Arial;
   background: white;
   border: solid 1px;
   border-color: lightgrey;
   border-radius: 4px;
   pointer-events: none;
 }

 .toolHead {
   padding: 5px;
   text-align: left;
   font-family: sans-serif;
   border-bottom: 2px solid #2196F3;
   font-size: 14px;
   /* border-bottom: 1px dashed black; */
   -webkit-text-fill-color: #2196F3;
 }

 td {
   padding: 5px;
   text-align: right;
   font-family: sans-serif;
 }

JavaScript

var lines = dc.seriesChart('#line');
var stacks = dc.barChart('#stack');

var timeFmt = d3.timeParse('%d-%b-%Y %H:%M');
var numberFormat = d3.format('.2f');

d3.csv('https://raw.githubusercontent.com/JaelB/Generic-DC.js-Chart/master/fiddle3.csv').then(function(data) {

  var ndx = crossfilter(data);

  var XDimension = ndx.dimension(function(d) {
    return d.no;
  });

  var YDimension = XDimension.group().reduce(
    function reduceAdd(p, d) {
      ++p.count;
      p.bottom += +d.bottom;
      p.top += +d.top;
      p.extra += +d.extra;
      p.avg = p.bottom ? (p.top / p.bottom) : 0;
      p[d.sub_no] = (p[d.sub_no] || 0) + p.bottom ? (p.top / p.bottom) : 0;

      return p;
    },
    function reduceRemove(p, d) {
      --p.count;
      p.bottom -= +d.bottom;
      p.top -= +d.top;
      p.extra -= +d.extra;
      p.avg = p.bottom ? (p.top / p.bottom) : 0;
      p[d.sub_no] = (p[d.sub_no] || 0) - p.bottom ? (p.top / p.bottom) : 0;

      return p;
    },
    function reduceInitial() {
      return {
        count: 0,
        bottom: 0,
        top: 0,
        extra: 0,
        avg: 0
      };
    });

  var dateDimension = ndx.dimension(function(d) {
    return [timeFmt(d.date), d.no, d.sub_no, d.type, +d.top, +d.bottom];
  });
  var lineGroup = dateDimension.group().reduceSum(function(d) {
    if (d.type == 'X' || d.type == 'Y')
      return +d.extra;
    else return null;
  });

  var dummy = ndx.dimension(function(d) {
    return timeFmt(d.date);
  });
  var startDate = timeFmt(dummy.bottom(1)[0].date);
  var endDate = timeFmt(dummy.top(1)[0].date);


  function sel_stack(sub) {
    return function(dataItem) {
      return dataItem.value[sub];
    };
  }

  function remove_empty_bins(source_group) {
    return {
      all: function() {
        return source_group.all().filter(function(d) {
          return d.value != 0;
        });
      }
    };
  }


  var div = d3.select("body").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);


 ...