Built with blockbuilder.org
forked from azerton‘s block: fresh block
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<div class="searchcontainer">
<input id="search">
<button type="button" id="searchbutton">Search</button>
<button type="button" id="dnsbutton">DNS</button>
<button type="button" id="httpbutton">HTTP</button>
</div>
<div id="container" class="svg-container">
<svg width="1680" height="700"></svg>
</div>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.js"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script>
// Data processing
// ===============
d3.json("network.json", function (error, graph) {
console.log("Number of nodes at start: " + graph.nodes.length)
if (error) throw error;
// Prepare all data structures
var linksUpdate, linksEnter, linksMerge, linksExit, nodesUpdate, nodesEnter, nodesMerge, nodesExit, g_links, g_nodes, filteredNodes;
// Define color palet to use for nodes
var color = d3.scaleOrdinal(d3.schemeCategory10);
// Tooltips
var tool_tip = d3
.tip()
.attr("class", "d3-tip")
.offset([0, 0])
.html(function (d) {
return "IP: " + d.id + "<br/>" + "Links: " + d.value;
});
// The SVG element already exists, get a reference to it
var svg = d3
.select("svg")
.classed("svg-content", true)
svg.call(tool_tip);
g_links = svg.append("g").attr("class", "links")
g_nodes = svg.append("g").attr("class", "nodes")
// Describe zoom behavior
var zoom = d3.zoom()
.scaleExtent([1 / 10, 4])
.on("zoom", zoomed);
function zoomed() {
var transform = d3.event.transform;
g_nodes.attr("transform", d3.event.transform);
g_links.attr("transform", d3.event.transform);
}
// Describe forces to be used for the simulation
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}))
.force("center", d3.forceCenter(svg.attr("width") / 2, svg.attr("height") / 2))
.force("charge", d3.forceManyBody().strength(function (d) {
return Math.log(d.value) * -4
}));
svg
.style("fill", "none")
.style("pointer-events", "all")
.call(zoom);
function dragsubject() {
searchRadius = 40;
return simulation.find(d3.event.x - svg.attr("height"), d3.event.y - svg.attr("height") / 2, searchRadius);
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// Search
var optArray = [];
for (var i = 0; i < svg.nodes.length - 1; i++) {
optArray.push(svg.nodes[i].id);
}
optArray = optArray.sort();
$(function () {
$("#search").autocomplete({
source: optArray
});
});
function searchNode() {
console.log("search clicked")
}
// Bind onclick
$('#searchbutton').click(function () {
searchNode();
});
// Bind onclick
$('#dnsbutton').click(function () {
filter("DNS");
});
// Bind onclick
$('#httpbutton').click(function () {
filter("HTTP");
});
function filter(filter) {
// Remove all nodes without links
removeOrphanedNodes();
redraw(filter);
}
function removeOrphanedNodes() {
var ip_arr = [];
filteredNodes = [];
// Iterate all IPs
for (var link in graph.links) {
ip_arr.push(graph.links[link]["source"]["id"]);
ip_arr.push(graph.links[link]["target"]["id"]);
}
ip_arr = unique(ip_arr);
for (var node in graph.nodes) {
for (ip in ip_arr) {
if (ip_arr[ip] == (graph.nodes[node]["id"])) {
filteredNodes.push(graph.nodes[node]);
}
}
}
graph.nodes = filteredNodes;
}
function redraw(filter) {
filteredLinks = graph.links.filter(function (i, n) {
return i.proto == filter;
});
linksUpdate = g_links
.selectAll("line")
.data(filteredLinks, function (d) {
return d.id;
});
linksEnter = linksUpdate.enter()
.append("line")
.style("opacity", 1)
.attr("stroke-width", function (d) {
return 0.3
});
linksMerge = linksUpdate.merge(linksEnter);
linksExit = linksUpdate.exit().transition()
.style("opacity", 0)
.duration(500)
.remove();
nodesUpdate = g_nodes
.selectAll("circle")
.data(graph.nodes, function (d) {
return d.id;
});
nodesEnter = nodesUpdate.enter()
.append("circle")
.style("opacity", 1)
.attr("r", function (d) {
return Math.log(d.value);
})
.attr("fill", function (d) {
return color(d.group);
})
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on('mouseover', tool_tip.show) //Added
.on('mouseout', tool_tip.hide); //Added
nodesMerge = nodesUpdate.merge(nodesEnter);
nodesExit = nodesUpdate.exit().transition()
.style("opacity", 0)
.duration(500)
.remove();
nodesMerge.append("title")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function (d) {
return d.has_ip_layer
});
simulation
.nodes(graph.nodes)
.on("tick", ticked)
.force("link")
.links(filteredLinks);
}
function ticked() {
linksMerge
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
nodesMerge
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
}
function unique(list) {
var result = [];
$.each(list, function (i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
return result;
}
// Draw the graph
redraw();
})
;
</script>