block by mpmckenna8 9fca06f5001d3cc7001409b508d45d4d

hacky solution for friends' problem

Full Screen

index.html

<!DOCTYPE html >
  <head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    .node circle {
  fill: #999;
}

.node text {
  font: 10px sans-serif;
}

.node--internal circle {
  fill: #555;
}

.node--internal text {
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}

.link {
  fill: none;
  stroke: #555;
  stroke-opacity: 0.4;
  stroke-width: 1.5px;
}

  </style>
</head>
<body>
  <svg class = 'squares'></svg>
  <svg class= 'treemap' width = "800" height = "896" ></svg>
  <script>

    var data = [
      {
      'name': 'request-promise',
      "dependencies": {
        "name": "request-promise",
        "children": [{
          "name": "dependency",
          "children": [{
            "name": "request-promise-core"
          }, {
            "name": "bluebird"
          }, {
            "name": "stealthy-require"
          }, {
            "name": "tough-cookie"
          }]
        }, {
          "name": "devDependency",
          "children": [{
            "name": "body-parser"
          }, {
            "name": "chai"
          }, {
            "name": "chalk"
          }, {
            "name": "gulp"
          }, {
            "name": "gulp-coveralls"
          }, {
            "name": "gulp-eslint"
          }, {
            "name": "gulp-istanbul"
          }, {
            "name": "gulp-mocha"
          }, {
            "name": "lodash"
          }, {
            "name": "publish-please"
          }, {
            "name": "request"
          }, {
            "name": "rimraf"
          }, {
            "name": "run-sequence"
          }]
        }, {
          "name": "peerDependency",
          "children": [{
            "name": "request"
          }]
        }]
      }},
      {
        'name': 'webpack',
      "dependencies": {
      "name": "webpack",
      "children": [{
        "name": "dependency",
        "children": [{
          "name": "acorn"
        }, {
          "name": "acorn-dynamic-import"
        }, {
          "name": "ajv"
        }, {
          "name": "ajv-keywords"
        }, {
          "name": "async"
        }, {
          "name": "enhanced-resolve"
        }, {
          "name": "interpret"
        }, {
          "name": "json-loader"
        }, {
          "name": "json5"
        }, {
          "name": "loader-runner"
        }, {
          "name": "loader-utils"
        }, {
          "name": "memory-fs"
        }, {
          "name": "mkdirp"
        }, {
          "name": "node-libs-browser"
        }, {
          "name": "source-map"
        }, {
          "name": "supports-color"
        }, {
          "name": "tapable"
        }, {
          "name": "uglify-js"
        }, {
          "name": "watchpack"
        }, {
          "name": "webpack-sources"
        }, {
          "name": "yargs"
        }]
      }, {
        "name": "devDependency",
        "children": [{
          "name": "beautify-lint"
        }, {
          "name": "benchmark"
        }, {
          "name": "bundle-loader"
        }, {
          "name": "codacy-coverage"
        }, {
          "name": "codecov.io"
        }, {
          "name": "coffee-loader"
        }, {
          "name": "coffee-script"
        }, {
          "name": "coveralls"
        }, {
          "name": "css-loader"
        }, {
          "name": "es6-promise-polyfill"
        }, {
          "name": "eslint"
        }, {
          "name": "eslint-plugin-node"
        }, {
          "name": "express"
        }, {
          "name": "extract-text-webpack-plugin"
        }, {
          "name": "file-loader"
        }, {
          "name": "i18n-webpack-plugin"
        }, {
          "name": "istanbul"
        }, {
          "name": "jade"
        }, {
          "name": "jade-loader"
        }, {
          "name": "js-beautify"
        }, {
          "name": "less"
        }, {
          "name": "less-loader"
        }, {
          "name": "lodash"
        }, {
          "name": "mocha"
        }, {
          "name": "mocha-lcov-reporter"
        }, {
          "name": "nsp"
        }, {
          "name": "raw-loader"
        }, {
          "name": "react"
        }, {
          "name": "react-dom"
        }, {
          "name": "script-loader"
        }, {
          "name": "should"
        }, {
          "name": "simple-git"
        }, {
          "name": "sinon"
        }, {
          "name": "style-loader"
        }, {
          "name": "url-loader"
        }, {
          "name": "val-loader"
        }, {
          "name": "vm-browserify"
        }, {
          "name": "webpack-dev-middleware"
        }, {
          "name": "worker-loader"
        }]
      }]
    }},
    {
      'name': 'yargs',
      "dependencies": {
      "name": "yargs",
      "children": [{
        "name": "dependency",
        "children": [{
          "name": "camelcase"
        }, {
          "name": "cliui"
        }, {
          "name": "decamelize"
        }, {
          "name": "get-caller-file"
        }, {
          "name": "os-locale"
        }, {
          "name": "read-pkg-up"
        }, {
          "name": "require-directory"
        }, {
          "name": "require-main-filename"
        }, {
          "name": "set-blocking"
        }, {
          "name": "string-width"
        }, {
          "name": "which-module"
        }, {
          "name": "y18n"
        }, {
          "name": "yargs-parser"
        }]
      }, {
        "name": "devDependency",
        "children": [{
          "name": "chai"
        }, {
          "name": "chalk"
        }, {
          "name": "coveralls"
        }, {
          "name": "cpr"
        }, {
          "name": "cross-spawn"
        }, {
          "name": "es6-promise"
        }, {
          "name": "hashish"
        }, {
          "name": "mocha"
        }, {
          "name": "nyc"
        }, {
          "name": "rimraf"
        }, {
          "name": "standard"
        }, {
          "name": "standard-version"
        }, {
          "name": "which"
        }, {
          "name": "yargs-test-extends"
        }]
      }]
    }
    },
    {
      "name": 'bluebird',
      "dependencies": {
      "name": "bluebird",
      "children": [{
        "name": "devDependency",
        "children": [{
          "name": "acorn"
        }, {
          "name": "baconjs"
        }, {
          "name": "bluebird"
        }, {
          "name": "body-parser"
        }, {
          "name": "browserify"
        }, {
          "name": "cli-table"
        }, {
          "name": "co"
        }, {
          "name": "cross-spawn"
        }, {
          "name": "glob"
        }, {
          "name": "grunt-saucelabs"
        }, {
          "name": "highland"
        }, {
          "name": "istanbul"
        }, {
          "name": "jshint"
        }, {
          "name": "jshint-stylish"
        }, {
          "name": "mkdirp"
        }, {
          "name": "mocha"
        }, {
          "name": "open"
        }, {
          "name": "optimist"
        }, {
          "name": "rimraf"
        }, {
          "name": "rx"
        }, {
          "name": "serve-static"
        }, {
          "name": "sinon"
        }, {
          "name": "uglify-js"
        }, {
          "name": "kefir"
        }]
      }]
    }
  }];

//////////////////////////////////////////////////
// Clicking the black boxes will render the dependency tree map
// The bug is in the node data join
// The paths seem to render fine but old nodes are not removed
////////////////////////////////////////////////

  const dependencies = d3.select('.treemap'),
  width = window.innerHeight- 250,
  height = window.innerWidth- 250;


  const treemap = d3.tree()
  .size([height, width]);


  const buildDependencies = function(pkg){

    console.log(pkg)

    d3.selectAll('g.node').remove()
    const stratify = d3.stratify()
      .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });

    let nodes = d3.hierarchy(pkg.dependencies, function(d) {
      return d.children;
    });

    nodes = treemap(nodes);  //here is where stratify is called


    const updateLinks = dependencies.selectAll(".link")
    .data(nodes.descendants().slice(1))

    const enterLinks = updateLinks.enter().append("path")
      .attr("class", "link")

    const exitLink = updateLinks.exit().remove();

     updateLinks.merge(enterLinks).attr("d", function(d) {
                return "M" + d.y + "," + d.x
                  + "C" + (d.y + d.parent.y) / 2 + "," + d.x
                  + " " + (d.y + d.parent.y) / 2 + "," + d.parent.x
                  + " " + d.parent.y + "," + d.parent.x;
                });



    const updateNodes = dependencies.selectAll("g.nodes")
    .data(nodes.descendants(), d => d)


    const enterNodes = updateNodes.enter().append("g")
    .attr("class", function(d) {
          return "node" +
    (d.children ? " node--internal" : " node--leaf"); })
    .attr("transform", function(d) {
    return "translate(" + d.y + "," + d.x + ")"; })


    enterNodes.append("circle")
    .attr("r", function(d) { return 15; })
    .style("stroke", function(d) { return 'yellow'; })
    .style("fill", function(d) { return 'green'; });

    enterNodes.append("text")
    .attr("dy", ".35em")
    .attr("x", function(d) {
    return 25 })
    .style("text-anchor", function(d) {
    return d.children ? "end" : "start"; })
    .text(function(d) { return d.data.name; });

    updateNodes.merge(enterNodes)

    const exitNode = updateNodes.exit().remove();

}

  const squares = d3.select('svg.squares')
  .attr('height', 400).attr('width', 400)

  squares.append('g').selectAll('rects')
  .data(data).enter()
  .append('rect').attr('x', (d, i) => {
    return i * 100
  }).attr('y', (d, i) => {
    console.log(d)
    return 100
  })
  .attr('width', 50).attr('height', 50)
  .attr('fill', 'black')
  .on('click', (d) => {
    console.log(d)
    buildDependencies(d)
  })






  </script>
</body>

tree dependency block

<!DOCTYPE html >
  <head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    .node circle {
  fill: #999;
}

.node text {
  font: 10px sans-serif;
}

.node--internal circle {
  fill: #555;
}

.node--internal text {
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}

.link {
  fill: none;
  stroke: #555;
  stroke-opacity: 0.4;
  stroke-width: 1.5px;
}

  </style>
</head>
<body>
  <svg class = 'squares'></svg>
  <svg class= 'treemap' width = "800" height = "896" ></svg>
  <script>

    var data = [
      {
      'name': 'request-promise',
      "dependencies": {
        "name": "request-promise",
        "children": [{
          "name": "dependency",
          "children": [{
            "name": "request-promise-core"
          }, {
            "name": "bluebird"
          }, {
            "name": "stealthy-require"
          }, {
            "name": "tough-cookie"
          }]
        }, {
          "name": "devDependency",
          "children": [{
            "name": "body-parser"
          }, {
            "name": "chai"
          }, {
            "name": "chalk"
          }, {
            "name": "gulp"
          }, {
            "name": "gulp-coveralls"
          }, {
            "name": "gulp-eslint"
          }, {
            "name": "gulp-istanbul"
          }, {
            "name": "gulp-mocha"
          }, {
            "name": "lodash"
          }, {
            "name": "publish-please"
          }, {
            "name": "request"
          }, {
            "name": "rimraf"
          }, {
            "name": "run-sequence"
          }]
        }, {
          "name": "peerDependency",
          "children": [{
            "name": "request"
          }]
        }]
      }},
      {
        'name': 'webpack',
      "dependencies": {
      "name": "webpack",
      "children": [{
        "name": "dependency",
        "children": [{
          "name": "acorn"
        }, {
          "name": "acorn-dynamic-import"
        }, {
          "name": "ajv"
        }, {
          "name": "ajv-keywords"
        }, {
          "name": "async"
        }, {
          "name": "enhanced-resolve"
        }, {
          "name": "interpret"
        }, {
          "name": "json-loader"
        }, {
          "name": "json5"
        }, {
          "name": "loader-runner"
        }, {
          "name": "loader-utils"
        }, {
          "name": "memory-fs"
        }, {
          "name": "mkdirp"
        }, {
          "name": "node-libs-browser"
        }, {
          "name": "source-map"
        }, {
          "name": "supports-color"
        }, {
          "name": "tapable"
        }, {
          "name": "uglify-js"
        }, {
          "name": "watchpack"
        }, {
          "name": "webpack-sources"
        }, {
          "name": "yargs"
        }]
      }, {
        "name": "devDependency",
        "children": [{
          "name": "beautify-lint"
        }, {
          "name": "benchmark"
        }, {
          "name": "bundle-loader"
        }, {
          "name": "codacy-coverage"
        }, {
          "name": "codecov.io"
        }, {
          "name": "coffee-loader"
        }, {
          "name": "coffee-script"
        }, {
          "name": "coveralls"
        }, {
          "name": "css-loader"
        }, {
          "name": "es6-promise-polyfill"
        }, {
          "name": "eslint"
        }, {
          "name": "eslint-plugin-node"
        }, {
          "name": "express"
        }, {
          "name": "extract-text-webpack-plugin"
        }, {
          "name": "file-loader"
        }, {
          "name": "i18n-webpack-plugin"
        }, {
          "name": "istanbul"
        }, {
          "name": "jade"
        }, {
          "name": "jade-loader"
        }, {
          "name": "js-beautify"
        }, {
          "name": "less"
        }, {
          "name": "less-loader"
        }, {
          "name": "lodash"
        }, {
          "name": "mocha"
        }, {
          "name": "mocha-lcov-reporter"
        }, {
          "name": "nsp"
        }, {
          "name": "raw-loader"
        }, {
          "name": "react"
        }, {
          "name": "react-dom"
        }, {
          "name": "script-loader"
        }, {
          "name": "should"
        }, {
          "name": "simple-git"
        }, {
          "name": "sinon"
        }, {
          "name": "style-loader"
        }, {
          "name": "url-loader"
        }, {
          "name": "val-loader"
        }, {
          "name": "vm-browserify"
        }, {
          "name": "webpack-dev-middleware"
        }, {
          "name": "worker-loader"
        }]
      }]
    }},
    {
      'name': 'yargs',
      "dependencies": {
      "name": "yargs",
      "children": [{
        "name": "dependency",
        "children": [{
          "name": "camelcase"
        }, {
          "name": "cliui"
        }, {
          "name": "decamelize"
        }, {
          "name": "get-caller-file"
        }, {
          "name": "os-locale"
        }, {
          "name": "read-pkg-up"
        }, {
          "name": "require-directory"
        }, {
          "name": "require-main-filename"
        }, {
          "name": "set-blocking"
        }, {
          "name": "string-width"
        }, {
          "name": "which-module"
        }, {
          "name": "y18n"
        }, {
          "name": "yargs-parser"
        }]
      }, {
        "name": "devDependency",
        "children": [{
          "name": "chai"
        }, {
          "name": "chalk"
        }, {
          "name": "coveralls"
        }, {
          "name": "cpr"
        }, {
          "name": "cross-spawn"
        }, {
          "name": "es6-promise"
        }, {
          "name": "hashish"
        }, {
          "name": "mocha"
        }, {
          "name": "nyc"
        }, {
          "name": "rimraf"
        }, {
          "name": "standard"
        }, {
          "name": "standard-version"
        }, {
          "name": "which"
        }, {
          "name": "yargs-test-extends"
        }]
      }]
    }
    },
    {
      "name": 'bluebird',
      "dependencies": {
      "name": "bluebird",
      "children": [{
        "name": "devDependency",
        "children": [{
          "name": "acorn"
        }, {
          "name": "baconjs"
        }, {
          "name": "bluebird"
        }, {
          "name": "body-parser"
        }, {
          "name": "browserify"
        }, {
          "name": "cli-table"
        }, {
          "name": "co"
        }, {
          "name": "cross-spawn"
        }, {
          "name": "glob"
        }, {
          "name": "grunt-saucelabs"
        }, {
          "name": "highland"
        }, {
          "name": "istanbul"
        }, {
          "name": "jshint"
        }, {
          "name": "jshint-stylish"
        }, {
          "name": "mkdirp"
        }, {
          "name": "mocha"
        }, {
          "name": "open"
        }, {
          "name": "optimist"
        }, {
          "name": "rimraf"
        }, {
          "name": "rx"
        }, {
          "name": "serve-static"
        }, {
          "name": "sinon"
        }, {
          "name": "uglify-js"
        }, {
          "name": "kefir"
        }]
      }]
    }
  }];

//////////////////////////////////////////////////
// Clicking the black boxes will render the dependency tree map
// The bug is in the node data join
// The paths seem to render fine but old nodes are not removed
////////////////////////////////////////////////

  const dependencies = d3.select('.treemap'),
  width = window.innerHeight- 250,
  height = window.innerWidth- 250;

  const buildDependencies = function(pkg){


    const treemap = d3.tree()
    .size([height, width]);

    const stratify = d3.stratify()
      .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });
    let nodes = d3.hierarchy(pkg.dependencies, function(d) {
    return d.children;
    });
    nodes = treemap((nodes));  //here is where stratify is called




    const updateLinks = dependencies.selectAll(".link")
    .data(nodes.descendants().slice(1))

    const enterLinks = updateLinks.enter().append("path")
      .attr("class", "link")

    const exitLink = updateLinks.exit().remove();

     updateLinks.merge(enterLinks).attr("d", function(d) {
                return "M" + d.y + "," + d.x
                  + "C" + (d.y + d.parent.y) / 2 + "," + d.x
                  + " " + (d.y + d.parent.y) / 2 + "," + d.parent.x
                  + " " + d.parent.y + "," + d.parent.x;
                });



    const updateNodes = dependencies.selectAll("g.nodes")
    .data(nodes.descendants(), d => d)


    const enterNodes = updateNodes.enter().append("g")
    .attr("class", function(d) {
          return "node" +
    (d.children ? " node--internal" : " node--leaf"); })
    .attr("transform", function(d) {
    return "translate(" + d.y + "," + d.x + ")"; })


    enterNodes.append("circle")
    .attr("r", function(d) { return 15; })
    .style("stroke", function(d) { return 'yellow'; })
    .style("fill", function(d) { return 'green'; });

    enterNodes.append("text")
    .attr("dy", ".35em")
    .attr("x", function(d) {
    return 25 })
    .style("text-anchor", function(d) {
    return d.children ? "end" : "start"; })
    .text(function(d) { return d.data.name; });

    updateNodes.merge(enterNodes)

    const exitNode = updateNodes.exit().remove();
}

  const squares = d3.select('svg.squares')
  .attr('height', 400).attr('width', 400)

  squares.append('g').selectAll('rects').data(data).enter()
  .append('rect').attr('x', (d, i) => {
    return i * 100
  }).attr('y', (d, i) => {
    console.log(d)
    return 100
  })
  .attr('width', 50).attr('height', 50)
  .attr('fill', 'black')
  .on('click', (d) => {
    console.log(d)
    buildDependencies(d)
  })






  </script>
</body>