D3 tooltip not displaying - d3.js

I am having an issue displaying a tooltip while changing the color of the element the tooltip is for. I can comment out the tooltip code and the stroke color will change for the element but I need both the tooltip and the class change to occur. Any help is greatly appreciated. Here is what I am talking about:
var svg = d3.select("#app_dataPlane")
.append("svg")
.attr("width", width)
.attr("height", height);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return "<strong>DPID:</strong> <span style='color:red'>" + d.name + "</span><br />" + "<strong>State:</strong> <span style='color:red'>" + d.state + "</span>";
})
svg.call(tip);
var link = svg.selectAll(".link")
.data(topoObj.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", 2)
.on("mouseover", function (d) {
d3.selectAll(".link").classed("selectedLink", false);
d3.select(this).classed("selectedLink", true);
d3.select("#app_srcSwitch").html(d.source.name);
d3.select("#app_destSwitch").html(d.target.name);
});
var node = svg.selectAll(".switch")
.data(topoObj.nodes)
.enter()
.append("circle")
.attr("r", 6)
.attr("stroke", "white")
.attr("class","switch")
.attr("fill", function (d) {
if (d.group == 1) {
return "#15a9ff";
} else if (d.group == 2) {
return "#f98802";
} else if (d.group == 3) {
return "#ca5eff";
} else if (d.group == 4) {
return "#37a302";
} else if (d.group == 5) {
return "#00a4b0";
} else if (d.group == 6) {
return "#ff6054";
} else if (d.group == 7) {
return "#7b75ff";
} else if (d.group == 8) {
return "#b77264";
} else {
return "#8c8c8c";
}
})
.on('mouseover', function (d) {
d3.selectAll(".switch").classed("selectedSwitch", false);
d3.select(this).classed("selectedSwitch", true);
d3.select("#app_stateInfo").html(d.state);
d3.select("#app_dpidInfo").html(d.name);
d3.select("#app_InstanceInfo").html(d.onosInstance);
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.call(force.drag);

Subsequent calls to .on("mouseover", ...) overwrite what you've set there previously. To combine several things, execute them all in the handler function:
.on('mouseover', function (d) {
d3.selectAll(".switch").classed("selectedSwitch", false);
d3.select(this).classed("selectedSwitch", true);
d3.select("#app_stateInfo").html(d.state);
d3.select("#app_dpidInfo").html(d.name);
d3.select("#app_InstanceInfo").html(d.onosInstance);
tip.show();
});

Related

How to create a custom element in d3

The code is based on Denise's one on bl.ocks. How can I add to the existing code text and an icon to a node? I have almost got it by appending the needed elements but the problem is that circles appear at (0, 0) coordinate.
A picture is worth a thousand words,
and my target is having inside the nodes and where the nodes need to be, a text in the middle and an icon,
This is my current code, that works perfectly as long as the commented part is not uncommented (that's what I have tried to do)
let translateVar = [0,0];
let scaleVar = 1;
let radius = 50;
function create_pan_zoomable_svg(html_element, width, height) {
let svg = d3.select("body")
.append("svg")
.attr("width", "100%")
.attr("height", "100%")
.style("background-color", "#eeeeee")
.call(_zoom).on("dblclick.zoom", null)
.append("g");
d3.select("#zoom_in").on('click', function() { _zoom.scaleBy(svg, 2)});
d3.select("#zoom_out").on('click', function() { _zoom.scaleBy(svg, 0.5)});
create_marker(svg);
initialize_link_node(svg);
return svg;
}
var _zoom = d3.zoom()
.on("zoom", function() {
translateVar[0] = d3.event.transform.x;
translateVar[1] = d3.event.transform.y;
scaleVar = d3.event.transform.k;
svg.attr('transform', 'translate(' + translateVar[0] + ',' + translateVar[1] + ') scale(' + scaleVar + ')');
});
function create_marker(svg) {
let defs = svg.append("defs");
defs.append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 40)
.attr("refY", 0)
.attr("markerWidth", 8)
.attr("markerHeight", 8)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
}
function getScreenInfo() {
return {
width : ($(window).width()-translateVar[0])/scaleVar,
height : ($(window).height()-translateVar[1])/scaleVar,
centerx : (($(window).width()-translateVar[0])/scaleVar)/2,
centery : (($(window).height()-translateVar[1])/scaleVar)/2
};
}
let link, node, simulation;
function initialize_link_node(svg) {
let currentScreen = getScreenInfo();
simulation = d3.forceSimulation()
.force("link", d3.forceLink()
.id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody()
.strength(function(d) { return -20000;}))
.force("center", d3.forceCenter(currentScreen.centerx, currentScreen.centery));
link = svg.append("g").selectAll(".link");
node = svg.append("g").selectAll(".node");
}
function spawn_nodes(svg, graph, around_node, filtering_options) {
node = node.data(theData.nodes, function(d) {
return d.id;
});
let newNode = node.enter().append("g");
newNode = newNode.append("circle")
.attr("class", "node")
.attr("r", radius)
.attr("fill", function(d) {
return colors[d.type]
})
.attr("id", function(d) {
return d.id
});
/****************************************************
newNode.append("text")
.text( function(d) {
return d.id;
})
.style("fill", "red")
.style("text-anchor", "middle");
newNode.append("svg:image")
.attr("href", function(d) {
return dict_type_icon[d.type];
}).attr("width", "30")
.attr("height", "30");**************************/
newNode.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
);
node = node.merge(newNode);
link = link.data(theData.edges, function(d) {
return d.id;
});
let newLink = link.enter().append("line").attr("class", "link").attr("marker-end", "url(#arrow)");
newLink.append("title").text(function(d) {
return d.labeled;
});
link = link.merge(newLink);
node = node.merge(newNode);
simulation.nodes(theData.nodes).on("tick", ticked);
simulation.force("link").links(theData.edges);
simulation.alpha(1).alphaTarget(0).restart();
}
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;
}
function ticked() {
let currentScreen = getScreenInfo();
node
.attr("cx", function(d) {
return d.x = Math.max(radius, Math.min(currentScreen.width - radius, d.x));
})
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(currentScreen.height - radius, d.y)); });
link
.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; });
}
When I uncomment the circles appear at (0,0) point as you may have seen in the image.
I would appreciate if you could help me! Thank you.
Right now, you're turning newNode into a circles' selection:
newNode = newNode.append("circle")
//etc...
So, in order to keep it as a groups' selection, change that line to:
newNode.append("circle")
//etc...
Then, uncomment the commented part.
Finally, since that now node.merge(newNode) will be a groups' selection, change the cx and cy in ticked function to translate:
node.attr("transform", function(d) {
return "translate(" + (d.x = Math.max(radius, Math.min(currentScreen.width - radius, d.x))) +
"," + (d.y = Math.max(radius, Math.min(currentScreen.height - radius, d.y))) + ")";
});

Double-click on a node to fade out all but its immediate neighbours. Double-click to bring them back again

I am using the below code for the iamges and mouseover text. And now i have added the code for double click on a node to fade out all but it is not working and also link color is not changing. Can anyone help on this
var width = 960,
height = 500
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(0.1)
.charge(-120)
.linkDistance(30)
.size([width, height]);
var voronoi = d3.geom.voronoi()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.clipExtent([[0, 0], [width, height]]);
d3.json("miserables1.json", function(error, json) {
if (error) throw error;
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link", "fill:red; stroke:red;");
var node = svg.selectAll(".node")
.data(json.nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("svg:image")
.attr("xlink:href", function(d) { return d.imagen })
.on('dblclick', connectedNodes);
var circle = node.append("circle")
.attr("r", 4.5);
var label = node.append("text")
.attr("dy", ".35em")
.text(function(d) { return d.name; });
var cell = node.append("path")
.attr("class", "cell");
force.on("tick", function() {
cell
.data(voronoi(json.nodes))
.attr("d", function(d) { return d.length ? "M" + d.join("L") : null; });
link
.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; });
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
label
.attr("x", function(d) { return d.x + 8; })
.attr("y", function(d) { return d.y; });
});
});
var toggle = 0;
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
linkedByIndex[i + "," + i] = 1;
};
graph.links.forEach(function (d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function connectedNodes() {
if (toggle == 0) {
//Reduce the opacity of all but the neighbouring nodes
d = d3.select(this).node().__data__;
node.style("opacity", function (o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
});
link.style("opacity", function (o) {
return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
});
toggle = 1;
} else {
node.style("opacity", 1);
link.style("opacity", 1);
toggle = 0;
}
}

D3.js : Updating data on chart not working

Continuing to try and master the enter-update-exit pattern...
I've got a relatively simple reusable d3.js chart, and I want to be able to update the chart between two data sets. I'm getting close, but the chart is not updating properly.
You can see a fiddle here: http://jsfiddle.net/rolfsf/vba6n4sh/2/
Where did I mess up the enter-update-exit pattern?
The chart code looks like this:
function relativeSizeChart() {
var width = 1200,
margin = 0,
padding = 16,
r = d3.scale.linear(),
onTotalMouseOver = null,
onTotalClick = null,
onClusterMouseOver = null,
onClusterClick = null,
val = function(d){return d;};
totalFormat = function(d){return d;};
clusterFormat = function(d){return d;};
clusterFormat2 = function(d){return d;};
function chart(selection) {
selection.each(function(data) {
//console.log(data);
var clusterCount = data.Clusters.length,
totalColWidth = 0.3*width,
colWidth = (width - totalColWidth)/clusterCount,
height = colWidth + 2*padding,
maxRadius = (colWidth - 10)/2;
var svg = d3.select(this).selectAll("svg")
.data([data]);
var svgEnter = svg
.enter().append("svg")
.attr('class', function(d){
if( onTotalMouseOver !== null || onTotalClick !== null ||onClusterMouseOver !== null || onClusterClick !== null){
return 'clickable';
}else{
return 'static';
}
})
.attr("width", width)
.attr("height", height);
var background, clusterLines;
background = svgEnter.append("g")
.attr('class', 'background');
var headers = svgEnter.append("g")
.attr('class', 'headers')
.selectAll("text.header")
.data(data.Headers, function(d){return d;});
var total = svgEnter.append("g")
.attr('class', 'total');
var cluster = svgEnter.selectAll('g.cluster')
.data(data.Clusters,function(d){ return d;});
var clusterEnter = cluster
.enter().append("g")
.attr('class', 'cluster')
.attr('transform', function (d, i) {
return 'translate(' + (totalColWidth + i*colWidth) + ',0)';
});
var clusters = svg.selectAll('g.cluster');
r = d3.scale.linear()
.domain([0, d3.max(data.Clusters, function(d){return d[1];})])
.range([40, maxRadius]);
background .append("rect")
.attr("class", "chart-bg")
.attr('x', 0)
.attr('y', padding)
.attr('height', (height-padding))
.attr('width', width)
.attr('class', 'chart-bg');
background .append("g")
.attr('class', 'cluster-lines');
background .append("line")
.attr("class", "centerline")
.attr('x1', (totalColWidth - padding))
.attr('x2', width - (colWidth/2))
.attr('y1', (height+padding)/2)
.attr('y2', (height+padding)/2);
clusterLines = background.select('g.cluster-lines')
.selectAll("line")
.data(data.Clusters,function(d){ return d;})
.enter().append('line')
.attr('class', 'cluster-line');
headers .enter().append('text')
.attr('class', 'header');
total .append("rect")
.attr("class", "total-cluster")
.attr('x', padding)
.attr('y', 0.2*(height+(4*padding)))
.attr('height', 0.5*(height))
.attr('width', totalColWidth-(2*padding))
.attr('rx', 4)
.attr('ry', 4)
.on('mouseover', onTotalMouseOver)
.on('click', onTotalClick);
total .append("text")
.attr("class", "total-name")
.attr('x', totalColWidth/2 )
.attr('y', function(d, i) { return ((height+padding)/2) + (padding + 10); });
total .append("text")
.attr("class", "total-value")
.attr('x', totalColWidth/2 )
.attr('y', function(d, i) { return ((height+padding)/2); })
.text(totalFormat(0));
clusterEnter.append('circle')
.attr('class', 'bubble')
.attr('cx', function(d, i) { return colWidth/2; })
.attr('cy', function(d, i) { return (height+padding)/2;})
.attr("r", "50")
.on('mouseover', function(d, i, j) {
if (onClusterMouseOver != null) onClusterMouseOver(d, i, j);
})
.on('mouseout', function() { /*do something*/ })
.on('click', function(d, i){
onClusterClick(this, d, i);
});
clusterEnter.append('text')
.attr('class', 'cluster-value')
.attr('x', function(d, i) { return colWidth/2; })
.attr('y', function(d, i) { return ((height+padding)/2); })
.text(clusterFormat(0));
clusterEnter.append('text')
.attr('class', 'cluster-value-2')
.attr('x', function(d, i) { return colWidth/2; })
.attr('y', function(d, i) { return ((height+padding)/2) + (padding + 10); })
.text(clusterFormat2(0));
//update attributes
clusterLines.attr('x1', function(d, i) { return totalColWidth + i*colWidth })
.attr('x2', function(d, i) { return totalColWidth + i*colWidth })
.attr('y1', function(d, i) { return padding })
.attr('y2', function(d, i) { return (height); });
headers .attr('x', function(d, i) {
if(i === 0){
return (totalColWidth/2);
}else{
return (totalColWidth + (i*colWidth) - (colWidth/2))
}
})
.attr('y', 12);
//clean up old
svg .exit().remove();
cluster .exit().selectAll('circle.bubble')
.style("opacity", 1)
.style("fill", "#DDD")
.style("stroke", "#DDD")
.transition()
.duration(500)
.style("opacity", 0);
cluster .exit().remove();
headers .exit().remove();
function update(data) {
//update with data
svg .selectAll('text.total-value')
.transition()
.delay(400)
.duration(1000)
.tween( 'text', function(d, i) {
var currentValue = +this.textContent.replace(/\D/g,'');
var interpolator = d3.interpolateRound( currentValue, d.Total[1] );
return function( t ) {
this.textContent = totalFormat(interpolator(t));
};
});
svg .selectAll('text.total-name')
.text(val(data.Total[0]));
svg .selectAll('circle')
.attr('class', function(d, i) {
if(d[1] === 0){ return 'bubble empty';}
else {return 'bubble';}
})
.transition()
.duration(1000)
.delay(function(d, i) { return 500 + (i * 100); })
.ease('elastic')
.attr("r", function (d, i) { return r(d[1]); });
svg .selectAll('text.cluster-value')
.transition()
.delay(function(d, i) { return 500 + (i * 100); })
.duration(1000)
.tween( 'text', function(d, i) {
var currentValue = +this.textContent.replace(/\D/g,'');
var interpolator = d3.interpolateRound( currentValue, d[1] );
return function( t ) {
this.textContent = clusterFormat(interpolator(t));
};
});
svg .selectAll('text.cluster-value-2')
.transition()
.delay(function(d, i) { return 500 + (i * 100); })
.duration(1000)
.tween( 'text', function(d, i) {
var currentValue = +this.textContent.replace(/\D/g,'');
var interpolator = d3.interpolateRound( currentValue, d[0] );
return function( t ) {
this.textContent = clusterFormat2(interpolator(t));
};
});
headers .text(function(d, i){return d});
}
update(data);
});
}
chart.totalFormat = function(_) {
if (!arguments.length) return totalFormat;
totalFormat = _;
return chart;
};
chart.clusterFormat = function(_) {
if (!arguments.length) return clusterFormat;
clusterFormat = _;
return chart;
};
chart.clusterFormat2 = function(_) {
if (!arguments.length) return clusterFormat2;
clusterFormat2 = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.onTotalClick = function(_) {
if (!arguments.length) return onTotalClick;
onTotalClick = _;
return chart;
};
chart.onTotalMouseOver = function(_) {
if (!arguments.length) return onTotalMouseOver;
onTotalMouseOver = _;
return chart;
};
chart.onClusterClick = function(_) {
if (!arguments.length) return onClusterClick;
onClusterClick = _;
return chart;
};
chart.onClusterMouseOver = function(_) {
if (!arguments.length) return onClusterMouseOver;
onClusterMouseOver = _;
return chart;
};
return chart;
}
my sample data looks like this
var data = {
"data1": {
Headers: ["Total", "Col 1A", "Col 2A", "Col 3A", "Col 4A"],
Total: ["Total # of Widgets", 1200],
Clusters: [
[100, 1200],
[67, 800],
[42, 500],
[17, 198]
]
},
"data2": {
Headers: ["Total", "Col 1B", "Col 2B", "Col 3B", "Col 4B"],
Total: ["Total # of Widgets", 1200],
Clusters: [
[20, 245],
[31, 371],
[32, 386],
[12, 145]
]
}
}
Thanks!!
There are a couple of issues with your enter/update/exit pattern:
background = svgEnter.append("g")
.attr('class', 'background');
var headers = svgEnter.append("g")
.attr('class', 'headers')
.selectAll("text.header")
.data(data.Headers, function(d){return d;});
var total = svgEnter.append("g")
.attr('class', 'total');
This code is referencing svgEnter, which is OK the first time through, as svgEnter has a non-empty selection (it contains the svg you create a little earlier).
On subsequent calls to this function, svgEnter will contain an empty selection, as the svg element already exists. So, I have modified this part of your code to:
svgEnter.append('g')
.attr('class', 'background');
var background = svg.selectAll('g.background');
svgEnter.append('g')
.attr('class', 'headers')
var headers = svg.selectAll('g.headers').selectAll('text.header')
.data(data.Headers, function(d) { return d; });
svgEnter.append('g')
.attr('class', 'total');
var total = svg.selectAll('g.total');
This will create the g elements if we also have to create the svg element. It will then create the variables similar to your existing code using selections from the svg element.
I think that they're the only changes I made, the rest of your code works as expected.
An updated fiddle is at http://jsfiddle.net/vba6n4sh/9/

D3 Force Directed Map Source and Target Properties

Is it possible to use names other than source and target for a D3 Force Directed Map? I am connecting to an API that provides me with the needed information but they are supplying it as 'src-port' and 'dst-port'. If I change the names in a static JSON file to 'source' and 'target' the links on my map appear. If I leave it as is, I get the following error message:
e.source is undefined
Is there a way I can specify what property names to look for instead of using the defaults, 'source' and 'target'?
Here is the complete code to work with:
function buildMap(node, ids, mode) {
d3.select("svg").remove();
width = 960,
height = 500;
svg = d3.select(node).append("svg")
.attr("width", width)
.attr("height", height)
.attr("id","chart")
.attr("preserveAspectRatio","xMidYMid")
.attr("viewBox","0 0 960 500");
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-220)
.linkDistance(40)
.size([width, height]);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return "<strong>DPID:</strong> <span style='color:red'>" + d.dpid + "</span><br />" + "<strong>Type:</strong> <span style='color:red'>" + d.type + "</span>";
})
svg.call(tip);
//d3.json("http://192.168.1.82:9000/wm/onos/topology", function(error, graph) {
d3.json("http://localhost:9001/data/nodes.json", function(error, graph) {
force
.nodes(graph.switches)
.links(graph.links.forEach(function(l) {
l.source = l["src-port"];
l.target = l["dst-port"];
})
)
.on("tick", tick)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll(".node")
.data(graph.switches)
.enter().append("circle")
.attr("class", function(d) {
//if(d.type == undefined) {
return "node";
//} else {
// return d.type;
//}
})
.attr("r", function(d) {
//if(d.type == undefined) {
return 5;
//} else {
// switch(d.type) {
// case "core":
// return 10;
// break;
// case "agg":
// return 8;
// break;
// default:
// return 5;
// }
//}
})
.style("fill", function(d) {
//var count = ids.length;
//if(count <= 0)
// return d.color;
var color = "#15a9ff";
//if(d3.select(this).style("fill") == color){
// for (i = 0; i <= count; i++) {
// if(ids[i] != undefined) {
// if(ids[i].attributes.id == d.instance_id) {
// color = d.color;
// }
// }
// }
return color;
// }
}
)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.call(force.drag)
.on("click", function (d) {
enyo.Signals.send("onNodeSelected", d);
});
//node.append("title")
// .text(function(d) { return d.name; });
function tick(e) {
//if(mode == "tree") {
// var k = 6 * e.alpha;
// graph.links.forEach(function(d, i) {
// d.source.y -= k;
// d.target.y += k;
// });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
link.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; });
//} else {
// link.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; });
// node.attr("cx", function(d) { return d.x; })
// .attr("cy", function(d) { return d.y; });
}
//}
});
}
There is no way to do this through the API; you would have to modify the source. One easy way of dealing with this is to simply copy the values in src-port and dst-port into source and target:
links.forEach(function(l) {
l.source = l.src-port;
l.target = l.dst-port;
});

D3 Force Directed Map conditionally setting fill color of a nodes

I am attempting to send in a set of IDs to my method that builds my Force Directed map. I loop through the nodes and I want to set the fill color of the nodes that are selected from the parent id. I have a list on the page where when you select an item from it it will highlight the additional nodes by matching the color. I can't seem to get the fill color right. Any help is greatly appreciated.
<code>
function buildAllForceDirectedMultiMap(node, ids) {
d3.select("svg").remove();
var width = 960,
height = 500;
var svg = d3.select(node).append("svg")
.attr("width", width)
.attr("height", height);
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return "<strong>DPID:</strong> <span style='color:red'>" + d.dpid + "</span><br />" + "<strong>Type:</strong> <span style='color:red'>" + d.type + "</span>";
})
svg.call(tip);
d3.json("http://atxapps.com/apps/data/onos/dataGetFDAllInstances.php", function(error, graph) {
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", function(d) {
if(d.type == undefined) {
return "node";
} else {
return d.type;
}})
.attr("r", function(d) {
if(d.type == undefined) {
return 5;
} else {
switch(d.type) {
case "core":
return 10;
break;
case "agg":
return 8;
break;
default:
return 5;
}
}})
.style("fill", function(d) {
var count = ids.length;
for (i = 0; i <= count; i++) {
if(ids[i] != undefined) {
if(ids[i].attributes.id == d.instance_id) {
return d.color;
} else {
return "#2a2a2a";
}}
}
return d.color;
}
)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.call(force.drag)
.on("click", function (d) {
//alert(d.dpid);
});
node.append("title")
.text(function(d) { return d.name; });
force.on("tick", function() {
link.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; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});
}
</code>
wound up having to select the instance of the d3 element I was working with. Code looks like this now
<pre>
.style("fill", function(d) {
var count = ids.length;
var color = "rgb(0, 0, 0)";
if(d3.select(this).style("fill") == color){
for (i = 0; i <= count; i++) {
if(ids[i] != undefined) {
if(ids[i].attributes.id == d.instance_id) {
color = d.color;
}
}
}
return color;
}
}
)
</pre>

Resources