chg: Dragable box for URLs of a domain

pull/14/merge
Raphaël Vinot 2018-01-16 17:48:11 +01:00
parent ffb255366c
commit ab37ced391
2 changed files with 61 additions and 39 deletions

View File

@ -8,16 +8,12 @@ var margin = {top: 20, right: 200, bottom: 30, left: 90},
var node_width = 0; var node_width = 0;
var node_height = 45; var node_height = 45;
var hostnode_tooltip = d3.select("body").append("div") var main_svg = d3.select("body").append("svg")
.attr("class", "tooltip")
.style("opacity", 0);
var init = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left) .attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom) .attr("height", height + margin.top + margin.bottom)
// Add background pattern // Add background pattern
var pattern = init.append("defs").append('pattern') var pattern = main_svg.append("defs").append('pattern')
.attr('id', 'backstripes') .attr('id', 'backstripes')
.attr('x', margin.left) .attr('x', margin.left)
.attr("width", node_width * 2) .attr("width", node_width * 2)
@ -29,23 +25,22 @@ pattern.append('rect')
.attr('height', height) .attr('height', height)
.attr("fill", "#EEEEEE"); .attr("fill", "#EEEEEE");
var background = init.append('rect') var background = main_svg.append('rect')
.attr('y', 0) .attr('y', 0)
.attr('width', width) .attr('width', width)
.attr('height', height) .attr('height', height)
.style('fill', "url(#backstripes)") .style('fill', "url(#backstripes)")
.on('click', function(d) { .on('click', function(d) {
hostnode_tooltip.transition() // Remove the
.duration(500) main_svg.selectAll('.overlay').remove()
.style("opacity", 0)
.style("z-index", -10);
}); });
// append the svg object to the body of the page // append the svg object to the body of the page
// appends a 'group' element to 'svg' // appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin // moves the 'group' element to the top left margin
var svg = init.append("g") var node_container = main_svg
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); .append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var i = 0, var i = 0,
duration = 750, duration = 750,
@ -59,12 +54,13 @@ root = d3.hierarchy(treeData, function(d) { return d.children; });
root.x0 = height / 2; root.x0 = height / 2;
root.y0 = 0; root.y0 = 0;
// Fancy expand all the nodes one after the other
// Collapse after the second level // Collapse after the second level
// root.children.forEach(collapse); //root.children.forEach(collapse);
update(root); update(root);
// Collapse the node and all it's children // Collapse the node and all it's children
function collapse(d) { function collapse(d) {
if(d.children) { if(d.children) {
@ -74,6 +70,7 @@ function collapse(d) {
} }
} }
// Gets the size of the box and increase it
function getBB(selection) { function getBB(selection) {
selection.each(function(d) { selection.each(function(d) {
d.data.total_width = d.data.total_width ? d.data.total_width : 0; d.data.total_width = d.data.total_width ? d.data.total_width : 0;
@ -81,6 +78,7 @@ function getBB(selection) {
}) })
} }
// Not used yet.
function urlnode_click(data) { function urlnode_click(data) {
var url = "url/" + data['uuid']; var url = "url/" + data['uuid'];
d3.json(url, function(error, u) { d3.json(url, function(error, u) {
@ -89,34 +87,60 @@ function urlnode_click(data) {
}) })
} }
// What happen when clicking on a domain (load a modal display)
function hostnode_click(d) { function hostnode_click(d) {
// Insert new svg element at this position
var overlay_hostname = main_svg.select("g")
.append("svg")
.append('g').attr('class', 'overlay');
overlay_hostname
.datum({x: 0, y: 0})
.attr('id', 'overlay_' + d.data.uuid)
.style("opacity", .9)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.call(d3.drag().on("drag", function(d, i) {
d.x += d3.event.dx
d.y += d3.event.dy
d3.select(this)
.attr("transform", "translate(" + d.x + "," + d.y + ")");
}));
overlay_hostname.append('rect')
.attr("rx", 6)
.attr("ry", 6)
.attr('x', d.y + 15)
.attr('y', d.x + 10)
.style("opacity", .9)
.attr("fill", "pink");
// Modal display // Modal display
var url = "hostname/" + d.data.uuid; var url = "/tree/hostname/" + d.data.uuid;
var pageX=d3.event.pageX;
var pageY=d3.event.pageY;
hostnode_tooltip.selectAll("ul").remove();
d3.json(url, function(error, urls) { d3.json(url, function(error, urls) {
if (error) throw error; if (error) throw error;
hostnode_tooltip.transition() urls.forEach(function(url, index, array){
.duration(200)
.style("opacity", .9)
.style("z-index", 1)
.style("left", (pageX) + "px")
.style("top", (pageY - 28) + "px");
var list = hostnode_tooltip.append('ul')
.attr("class", "list-group");
urls.forEach(function(url){
var jdata = JSON.parse(url) var jdata = JSON.parse(url)
var entry = list.append('li') overlay_hostname.append('text')
.attr("class", "list-group-item") .attr("class", "urls_in_overlay_" + d.data.uuid)
.attr("url_uuid", jdata['uuid']) .attr("url_uuid", jdata['uuid'])
.attr("dx", d.y + 20)
.attr("dy", d.x + 30 + (30 * index))
.attr("fill", "black")
.text(jdata['name']); .text(jdata['name']);
//.on('click', function(){urlnode_click(jdata)}); //.on('click', function(){urlnode_click(jdata)});
}) });
var urls_in_overlay = overlay_hostname.selectAll('text')
var maxTextWidth = d3.max(urls_in_overlay.nodes(), n => n.getComputedTextLength());
overlay_hostname
.attr('width', maxTextWidth + 10)
.attr('height', 30 * urls_in_overlay.size());
overlay_hostname.select('rect')
.attr('width', maxTextWidth + 10)
.attr('height', 30 * urls_in_overlay.size());
}); });
} }
// Recursiveluy generate the tree
function update(source) { function update(source) {
// reinitialize max_depth // reinitialize max_depth
@ -139,10 +163,10 @@ function update(source) {
// Update the nodes... // Update the nodes...
// TODO: set that ID to the ete3 node ID // TODO: set that ID to the ete3 node ID
var node = svg.selectAll('g.node') var node = node_container.selectAll('g.node')
.data(nodes, function(d) {return d.id || (d.id = ++i); }); .data(nodes, function(d) {return d.id || (d.id = ++i); });
// Enter any new modes at the parent's previous position. // Enter any new modes at the parent's previous position.
var nodeEnter = node.enter().append('g') var nodeEnter = node.enter().append('g')
.attr('class', 'node') .attr('class', 'node')
.attr("transform", function(d) { .attr("transform", function(d) {
@ -190,7 +214,7 @@ function update(source) {
// Normalize for fixed-depth. // Normalize for fixed-depth.
nodes.forEach(function(d){ d.y = d.depth * node_width}); nodes.forEach(function(d){ d.y = d.depth * node_width});
// Update pattern // Update pattern
init.selectAll('pattern') main_svg.selectAll('pattern')
.attr('width', node_width * 2) .attr('width', node_width * 2)
pattern.selectAll('rect') pattern.selectAll('rect')
.attr('width', node_width) .attr('width', node_width)
@ -353,7 +377,7 @@ function update(source) {
// ****************** links section *************************** // ****************** links section ***************************
// Update the links... // Update the links...
var link = svg.selectAll('path.link') var link = node_container.selectAll('path.link')
.data(links, function(d) { return d.id; }); .data(links, function(d) { return d.id; });
// Enter any new links at the parent's previous position. // Enter any new links at the parent's previous position.

View File

@ -1,10 +1,8 @@
# Web thing # Web thing
flask flask
flask-bootstrap flask-bootstrap
ete3
# Backend libs # Backend libs
git+https://github.com/viper-framework/har2tree.git git+https://github.com/viper-framework/har2tree.git
git+https://github.com/viper-framework/ScrapySplashWrapper.git git+https://github.com/viper-framework/ScrapySplashWrapper.git
# Required for the drawing (latest version)
git+https://github.com/etetoolkit/ete.git