This commit is contained in:
dethe 2013-07-24 10:09:43 -07:00
Родитель 4e296120da
Коммит 5d2cd74333
5 изменённых файлов: 144 добавлений и 151 удалений

Просмотреть файл

@ -9,19 +9,17 @@ var nodemap, edgemap;
var aggregate = new Emitter();
global.aggregate = aggregate;
global.filteredAggregate = {
nodes: [],
edges: []
};
aggregate.allnodes = [];
aggregate.sitenodes = [];
aggregate.thirdnodes = [];
aggregate.bothnodes = [];
aggregate.nodes = [];
aggregate.edges = [];
function resetData(){
aggregate.allnodes.length = 0;
aggregate.nodes.length = 0;
nodemap = {};
aggregate.sitenodes.length = 0;
aggregate.thirdnodes.length = 0;
aggregate.bothnodes.length = 0;
edgemap = {};
aggregate.edges.length = 0;
}
@ -71,15 +69,16 @@ aggregate.connectionAsObject = function(conn){
function applyFilter(filter){
resetData();
currentFilter = filter;
onLoad(allConnections);
}
aggregate.on('filter', applyFilter);
function onLoad(connections){
currentFilter(connections).forEach(onConnection);
connections.forEach(onConnection);
currentFilter();
currentVisualization.emit('init', filteredAggregate);
}
aggregate.on('load', onLoad);
@ -112,34 +111,20 @@ function onConnection(conn){
var sourcenode, targetnode, edge, nodelist, updated = false;
if (nodemap[connection.source]){
sourcenode = nodemap[connection.source];
var oldNodeType = sourcenode.nodeType;
sourcenode.update(connection, true);
if (oldNodeType !== sourcenode.nodeType){
moveNode(sourcenode, oldNodeType);
updated = true;
}
}else{
sourcenode = new GraphNode(connection, true);
nodemap[connection.source] = sourcenode;
nodelist = getNodeList(sourcenode.nodeType);
nodelist.push(sourcenode);
aggregate.allnodes.push(sourcenode);
aggregate.nodes.push(sourcenode);
updated = true;
}
if (nodemap[connection.target]){
targetnode = nodemap[connection.target];
var oldNodeType = targetnode.nodeType;
targetnode.update(connection, false);
if (oldNodeType !== targetnode.nodeType){
moveNode(targetnode, oldNodeType);
updated = true;
}
}else{
targetnode = new GraphNode(connection, false);
nodemap[connection.target] = targetnode;
nodelist = getNodeList(targetnode.nodeType);
nodelist.push(targetnode);
aggregate.allnodes.push(targetnode); // all nodes
aggregate.nodes.push(targetnode); // all nodes
updated = true
}
if (edgemap[connection.source + '->' + connection.target]){
@ -158,28 +143,14 @@ function onConnection(conn){
aggregate.on('connection', onConnection);
function getNodeList(nodeType){
switch(nodeType){
case 'site': return aggregate.sitenodes;
case 'thirdparty': return aggregate.thirdnodes;
case 'both': return aggregate.bothnodes;
default: throw new Error('It has to be one of the choices above');
}
}
function moveNode(node, oldNodeType){
var oldlist = getNodeList(oldNodeType);
var newlist = getNodeList(node.nodeType);
oldlist.splice(oldlist.indexOf(node), 1);
newlist.push(node);
}
function GraphEdge(source, target, connection){
this.source = source;
this.target = target;
this.name = source.name + '->' + target.name;
this.cookieCount = connection.cookie ? 1 : 0;
if (connection){
this.cookieCount = connection.cookie ? 1 : 0;
}
// console.log('edge: %s', this.name);
}
GraphEdge.prototype.lastAccess = function(){
@ -273,5 +244,123 @@ GraphNode.prototype.update = function(connection, isSource){
return this;
};
// Filtering
function nodesSortedByDate(nodes){
return nodes.map(function(node){
return [node.lastAccess, node];
}).sort().map(function(arr){
return arr[1];
});
}
function edgesForNodes(nodes){
var edgemap = {};
nodes.forEach(function(node){
node.linkedFrom.forEach(function)
})
}
function aggregateFromNodes(nodes){
var localmap = {};
var edgemap = {};
nodes.forEach(function(node){
localmap[node.name] = node;
node.linkedFrom.forEach(function(nodename){
var linkedNode = nodemap[nodename];
var edge = new GraphEdge(node, linkedNode);
edgemap[edge.name] = edge;
localmap[nodename] = linkedNode;
});
node.linkedTo.forEach(function(nodename){
var linkedNode = nodemap[nodename];
var edge = new GraphEdge(node, linkedNode);
edgemap[edge.name] = edge;
localmap[nodename] = linkedNode;
});
});
return {
nodes: Object.keys(localmap).map(function(name){
return localmap[name];
}),
edges: Object.keys(edgemap).map(function(name){
return edgemap[name];
})
};
}
// filters
aggregate.filters = {
daily: function daily(connections){
var now = Date.now();
var then = now - (24 * 60 * 60 * 1000);
var sortedNodes = nodesSortedByDate(aggregate.nodes);
console.log('daily filter before: %s', aggregate.nodes.length);
// filter
// find index where we go beyond date
var i;
for (i = sortedNodes.length - 1; i > -1, i--){
if (sortedNodes[i].lastAccess < then){
break;
}
}
var filteredNodes = sortedNodes.slice(i);
// Done filtering
console.log('daily filter after: %s', filteredNodes.length);
return aggregateFromNodes(filteredNodes);
},
weekly: function weekly(connections){
var now = Date.now();
var then = now - (7 * 24 * 60 * 60 * 1000);
var sortedNodes = nodesSortedByDate(aggregate.nodes);
console.log('weekly filter before: %s', sortedNodes.length);
// filter
// find index where we go beyond date
var i;
for (i = sortedNodes.length - 1; i > -1, i--){
if (sortedNodes[i].lastAccess < then){
break;
}
}
var filteredNodes = sortedNodes.slice(i);
console.log('weekly filter after: %s', filteredNodes.length);
return aggregateFromNodes(filteredNodes);
},
last10sites: function last10sites(connections){
var indices = [];
for (var i = 0; i < connections.length; i++){
if (connections[i][SOURCE_VISITED]){
indices.push(i);
}
}
console.log('last10sites filter before: %s', connections.length);
console.log('indices: %o', indices);
var filtered = connections;
if (indices.length > 9){
var cutpoint = indices.slice(-10)[0];
filtered = connections.slice(cutpoint);
}
console.log('last10sites filter after: %s', filtered.length)
return filtered;
},
recent: function recent(connections){
var indices = [];
for (var i = 0; i < connections.length; i++){
if (connections[i][SOURCE_VISITED]){
indices.push(i);
}
}
console.log('recent filter before: %s', connections.length);
console.log('indices: %o', indices);
var filtered = connections;
if (indices.length > 0){
var cutpoint = indices.slice(-1)[0];
filtered = connections.slice(cutpoint);
}
console.log('recent filter after: %s', filtered.length)
return filtered;
}
};
})(this);

Просмотреть файл

@ -26,11 +26,6 @@ clock.name = "clock";
clock.on('init', onInit);
clock.on('connection', onConnection);
clock.on('remove', onRemove);
clock.on('setFilter', setFilter);
function setFilter(){
addon.emit('setFilter', 'filter24hours');
}
function onInit(connections){
console.log("= onInit = allConnections.length = %s" , allConnections.length);

Просмотреть файл

@ -132,70 +132,12 @@ function switchVisualization(name){
}
localStorage.visualization = initCap(name);
currentVisualization = visualizations[name];
// currentVisualization.emit('setFilter');
resetAddtionalUI();
addon.emit('uiready');
}
// filters
var filters = {
daily: function daily(connections){
var now = Date.now();
var then = now - (24 * 60 * 60 * 1000);
console.log('then: %s and now: %s', then, now);
console.log('daily filter, before: %s', connections.length);
var filtered = connections.filter(function(connection){
return connection[TIMESTAMP] > then;
});
console.log('daily filter, after: %s', filtered.length);
return filtered;
},
weekly: function weekly(connections){
var now = Date.now();
var then = now - (7 * 24 * 60 * 60 * 1000);
console.log('then: %s and now: %s', then, now);
console.log('weekly filter: before: %s', connections.length);
var filtered = connections.filter(function(connection){
return connection[TIMESTAMP] > then;
});
console.log('weekly filter: after: %s', connections.length);
return filtered;
},
last10sites: function last10sites(connections){
var indices = [];
for (var i = 0; i < connections.length; i++){
if (connections[i][SOURCE_VISITED]){
indices.push(i);
}
}
console.log('last10sites filter: before: %s', connections.length);
console.log('indices: %o', indices);
if (indices > 9){
var cutpoint = indices.slice(-10)[0];
return connections.slice(cutpoint);
}else{
return connections;
}
},
recent: function recent(connections){
var indices = [];
for (var i = 0; i < connections.length; i++){
if (connections[i][SOURCE_VISITED]){
indices.push(i);
}
}
console.log('recent filter: before: %s', connections.length);
console.log('indices: %o', indices);
if (indices > 0){
var cutpoint = indices.slice(-1)[0];
return connections.slice(cutpoint);
}else{
return connections;
}
}
};
var currentFilter = filters[localStorage.currentFilter || 'last24Hours'];
var currentFilter = aggregate.filters[localStorage.currentFilter || 'last24Hours'];
function switchFilter(name){
console.log('switchFilter(' + name + ')');

Просмотреть файл

@ -11,6 +11,7 @@ visualizations.graph = graph;
graph.name = "graph";
var width = 1000, height = 1000;
var force, vis;
var filteredAggregate;
// There are three phases for a visualization life-cycle:
// init does initialization and receives the existing set of connections
@ -20,12 +21,6 @@ graph.on('init', onInit);
graph.on('connection', onConnection);
graph.on('remove', onRemove);
graph.on('reset', onReset);
graph.on('setFilter', setFilter);
function setFilter(){
//addon.emit('setFilter', 'filterLastXSites', 5);
//addon.emit('setFilter', 'filter24hours');
}
function onInit(connections){
console.log("= onInit = allConnections.length = %s" , allConnections.length);
@ -97,7 +92,7 @@ function polygonAsString(points, size){
function initGraph(){
// Initialize D3 layout and bind data
force = d3.layout.force()
.nodes(aggregate.allnodes)
.nodes(aggregate.nodes)
.links(aggregate.edges)
.charge(-500)
.size([width,height])
@ -149,22 +144,19 @@ function updateGraph(){
.remove();
var nodes = vis.selectAll('.node')
.data(aggregate.allnodes, function(node){ return node.name; });
.data(aggregate.nodes, function(node){ return node.name; });
nodes.call(force.drag);
nodes.enter().append('g')
.classed('visitedYes', function(node){ return node.visitedCount/node.howMany === 1 })
.classed('visitedNo', function(node){ return node.visitedCount/node.howMany === 0 })
.classed('visitedBoth', function(node){ return node.visitedCount/node.howMany > 0 && node.visitedCount/node.howMany < 1 })
.call(addShape)
.attr('data-name', function(node){ return node.name; })
.on('mouseenter', tooltip.show)
.on('mouseleave', tooltip.hide)
.classed('node', true);
nodes.exit()
.remove();
@ -175,7 +167,7 @@ window.updategGraph = updateGraph;
function addFavicon(selection){
selection.append("svg:image")
.attr("class", "favicon")
.attr("width", "16")
.attr("width", "16") // move these to the favicon class in css
.attr("height", "16")
.attr("x", "-8") // offset to make 16x16 favicon appear centered
.attr("y", "-8")
@ -194,8 +186,6 @@ function addCircle(selection){
function addShape(selection){
selection.filter('.visitedYes').call(addCircle).call(addFavicon);
selection.filter('.visitedNo').call(addTriangle).call(addFavicon);
selection.filter('.visitedBoth').call(addCircle).call(addFavicon);
// selection.filter('.visitedBoth').call(addSquare).call(addFavicon);
}
function addTriangle(selection){
@ -205,32 +195,15 @@ function addTriangle(selection){
.attr('data-name', function(node){ return node.name; });
}
// function addSquare(selection){
// selection
// .append('rect')
// .attr('x', -9)
// .attr('y', -9)
// .attr('width', 18)
// .attr('height', 18);
// }
function updateNodes(thenodes){
thenodes
.attr('transform', function(node){ return 'translate(' + node.x + ',' + node.y + ') scale(' + (1 + .03 * node.weight) + ')'; })
.classed('visitedYes', function(node){ return node.visitedCount/node.howMany == 1 })
.classed('visitedNo', function(node){ return node.visitedCount/node.howMany == 0 })
.classed('visitedBoth', function(node){ return node.visitedCount/node.howMany > 0 && node.visitedCount/node.howMany < 1 })
.classed('secureYes', function(node){ return node.secureCount/node.howMany == 1 })
.classed('secureNo', function(node){ return node.secureCount/node.howMany == 0 })
.classed('secureBoth', function(node){ return node.secureCount/node.howMany > 0 && node.secureCount/node.howMany < 1 })
// .classed('cookieYes', function(node){ return node.cookieCount/node.howMany == 1 })
// .classed('cookieNo', function(node){ return node.cookieCount/node.howMany == 0 })
// .classed('cookieBoth', function(node){ return node.cookieCount/node.howMany > 0 && node.cookieCount/node.howMany < 1 })
.attr('transform', function(node){ return 'translate(' + node.x + ',' + node.y + ') scale(' + (1 + .05 * node.weight) + ')'; })
.classed('visitedYes', function(node){ return node.visitedCount > 0 })
.classed('visitedNo', function(node){ return node.visitedCount == 0 })
.classed('secureYes', function(node){ return node.secureCount > 0 })
.classed('secureNo', function(node){ return node.secureCount == 0 })
.attr('data-timestamp', function(node){ return node.lastAccess.toISOString(); })
.attr('visited-scale', function(node){ return node.visitedCount/node.howMany; })
.attr('secure-scale', function(node){ return node.secureCount/node.howMany; })
.attr('cookie-scale', function(node){ return node.cookieCount/node.howMany; })
.classed('highlighted', function(edge){ return ( edge.visitedCount > 0 ) ? highlightVisited : highlightNeverVisited; });
// change shape if needed
}
@ -257,7 +230,7 @@ var graphLegend = document.querySelector(".graph-footer");
legendBtnClickHandler(graphLegend);
graphLegend.querySelector(".toggle-visited").addEventListener("click", function(event){
var visited = document.querySelectorAll(".visitedYes, .visitedBoth");
var visited = document.querySelectorAll(".visitedYes");
toggleVizElements(visited,"highlighted");
highlightVisited = !highlightVisited;
});

Просмотреть файл

@ -13,16 +13,10 @@ list.name = "list";
list.on("init", onInit);
list.on("conneciton", onConnection);
list.on("remove", onRemove);
list.on('setFilter', setFilter);
list.on("showFilteredTable", function(filter){
showFilteredTable(filter);
});
function setFilter(){
addon.emit('setFilter', 'filterNothing');
}
function onInit(connections){
vizcanvas.classList.add("hide"); // we don't need vizcanvas here, so hide it
// A D3 visualization has a two main components, data-shaping, and setting up the D3 callbacks