<!--
Library     : d3blocks
Author      : E.Taskesen
Mail        : erdogant@gmail.com
Github      : https://github.com/d3blocks/d3blocks
Licensed    : GPL3
Forked      : Mike Bostock; https://observablehq.com/@d3/sankey
-->

<!DOCTYPE html>
<html lang="en">
<!--<svg width="900" height="600"></svg>-->
<head>
    <meta charset="UTF-8">
    <title>{{ TITLE }}</title>
</head>
<body>

<script>
{% include "d3.v4.min.js" %}
{% include "d3-scale-chromatic.v1.min.js" %}
</script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<!-- Circle are black when hovered-->
<style>
.myCircle:hover {
  stroke: black;
}
</style>


<script>

// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 40},
    width = {{ WIDTH_FIG }} - margin.left - margin.right,
    height = {{ HEIGHT_FIG }} - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
    .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// Load data and let's do it.
var data = {{ json_data }}

window.addEventListener('DOMContentLoaded', function () {

    // Build and Show the Y scale
    var y = d3.scaleLinear()
      .domain([{{MIN_Y}}, {{MAX_Y}}])          // Note that here the Y scale is set manually
      .range([height, 0])
    svg.append("g").call( d3.axisLeft(y) )
    
    // Build and Show the X scale. It is a band scale like for a boxplot: each group has an dedicated RANGE on the axis. This range has a length of x.bandwidth
    var x = d3.scaleBand()
      .range([ 0, width ])
      .domain({{ X_ORDER }})
      .padding(0.05)     // This is important: it is the space between 2 groups. 0 means no padding. 1 is the maximum.
    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x))
    
    // Features of the histogram
    var histogram = d3.histogram()
          .domain(y.domain())
          .thresholds(y.ticks({{ BINS }}))    // Important: how many bins approx are going to be made? It is the 'resolution' of the violin plot
          .value(d => d)
    
    // Compute the binning for each group of the dataset
    var sumstat = d3.nest()  // nest function allows to group the calculation per level of a factor
      .key(function(d) { return d.x;})
      .rollup(function(d) {   // For each key..
        input = d.map(function(g) { return g.y;})    // Keep the variable called y
        bins = histogram(input)   // And compute the binning on it.
        return(bins)
      })
      .entries(data)
    
    // What is the biggest number of value in a bin? We need it cause this value will have a width of 100% of the bandwidth.
    var maxNum = 0
    for ( i in sumstat ){
      allBins = sumstat[i].value
      lengths = allBins.map(function(a){return a.length;})
      longuest = d3.max(lengths)
      if (longuest > maxNum) { maxNum = longuest }
    }
    
    // The maximum width of a violin must be x.bandwidth = the width dedicated to a group
    var xNum = d3.scaleLinear()
      .range([0, x.bandwidth()])
      .domain([-maxNum,maxNum])
    
    // Add the shape to this svg!
    svg
      .selectAll("myViolin")
      .data(sumstat)
      .enter()        // So now we are working group per group
      .append("g")
        .attr("transform", function(d){ return("translate(" + x(d.key) +" ,0)") } ) // Translation on the right to be at the group position
      .append("path")
          .datum(function(d){ return(d.value)})     // So now we are working bin per bin
          .style("stroke", "none")
          .style("fill","grey")
          .attr("d", d3.area()
              .x0( xNum(0) )
              .x1(function(d){ return(xNum(d.length)) } )
              .y(function(d){ return(y(d.x0)) } )
              .curve(d3.curveCatmullRom)    // This makes the line smoother to give the violin appearance. Try d3.curveStep to see the difference
          )
    

    // create a tooltip with the box ****************************
    var Tooltip = d3.select("#my_dataviz")
      .append("div")
      .style("opacity", 0)
      .attr("class", "tooltip")
      .style("background-color", "white")
      .style("border", "solid")
      .style("border-width", "2px")
      .style("border-radius", "5px")
      .style("padding", "5px")
      .style("position", "absolute")
    
    // Three function that change the tooltip when user hover / move / leave a cell
    var mouseover = function(d) {
    Tooltip
      .style("opacity", 1);
    
    // Increases size of the dot with 0.5
    d3.select(this)
      .style("r",  d.size + (0.5*d.size))
      .style("opacity", 0.8);
    }
    
    var mousemove = function(d) {
    Tooltip
      .html(d.tooltip)
    //  .html("Exact value: " + d[6])
      .style("left", (d3.mouse(this)[0]+70) + "px")
      .style("top", (d3.mouse(this)[1]) + "px")
    }
    
    var mouseleave = function(d) {
    Tooltip
      .style("opacity", 0)
    // Back to orignal dot-size
    d3.select(this)
      .style("r",  d[3])
    }
    
    // **********************************************************


    // Add individual points with jitter
    var jitterWidth = 40
    svg
      .selectAll("indPoints")
      .data(data)
      .enter()
      .append("circle")
        .attr("class", "myCircle")                        // Edge-color turns black when when hovered
        .attr("cx", function(d){return(x(d.x) + x.bandwidth()/2 - Math.random()*jitterWidth )})
        .attr("cy", function(d){return(y(d.y))})
        .attr("r", function(d){ return(d.size)})          // size
        .style("fill", function(d){ return(d.color)})     // fill color
        .attr("stroke", function(d){ return(d.stroke)})   // edge color
        .attr("opacity", function(d){ return(d.opacity)}) // opacity
        {{ MOUSEOVER }}
        {{ MOUSEMOVE }}
        {{ MOUSELEAVE }}

})

</script>