D3.js change text on mouseover, is it possible?

dzordz picture dzordz · Aug 30, 2013 · Viewed 10.7k times · Source

I have a force-directed graph, and I wanna to change text in the nodes on mouse over. I have tried to do this with placing a data of "full_name": in data array and then calling it on mouseover like I'm calling it for blue rectangle images. But it does not seems to work it and I'm not getting any error. So I don't know what is the problem..

You can see and edit example here: http://jsfiddle.net/dzorz/CqaLh/

and script looks like this:

    var data = {"nodes":[
                        {"name":"Action 1", "type":2, "slug": "", "entity":"employee" },
                        {"name":"Action 2", "type":3, "slug": "", "entity":"employee" },
                        {"name":"Action 4", "type":5, "slug": "", "value":265000, "entity":"employee"},
                        {"name":"Action 5", "type":6, "slug": "", "value":23000, "entity":"employee"},
                        {"name":"Action 3", "type":4, "slug": "", "value":115000, "entity":"employee"},
                        {"name":"YHO", "full_name":"Yahoo", "type":1, "slug": "www.yahoo.com", "entity":"company", "img_hrefD":"http://img4host.net/upload/30143226522090da3be7a.jpg", "img_hrefL":"http://img4host.net/upload/30145118522095467b7e3.jpg"},
                        {"name":"GGL", "full_name":"Google", "type":1, "slug": "www.google.com", "entity":"company", "img_hrefD":"http://img4host.net/upload/30143226522090da3be7a.jpg", "img_hrefL":"http://img4host.net/upload/30145118522095467b7e3.jpg" },
                        {"name":"BNG", "full_name":"Bing", "type":1, "slug": "www.bing.com", "entity":"company", "img_hrefD":"http://img4host.net/upload/30143226522090da3be7a.jpg", "img_hrefL":"http://img4host.net/upload/30145118522095467b7e3.jpg" },
                        {"name":"YDX", "full_name":"Yandex", "type":1, "slug": "", "entity":"company", "img_hrefD":"http://img4host.net/upload/30143226522090da3be7a.jpg", "img_hrefL":"http://img4host.net/upload/30145118522095467b7e3.jpg" }
                    ], 
            "links":[
                        {"source":0,"target":3,"value":10},
                        {"source":4,"target":3,"value":1},
                        {"source":1,"target":7,"value":10},
                        {"source":2,"target":4,"value":10},
                        {"source":4,"target":7,"value":1},
                        {"source":4,"target":5,"value":10},
                        {"source":4,"target":6,"value":10},
                        {"source":8,"target":4,"value":1}
                        ]
               }    



    var w = 560,
        h = 500,
        radius = d3.scale.log().domain([0, 312000]).range(["10", "50"]);

    var vis = d3.select("body").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

        vis.append("defs").append("marker")
        .attr("id", "arrowhead")
        .attr("refX", 25 + 3) /*must be smarter way to calculate shift*/
        .attr("refY", 2)
        .attr("markerWidth", 6)
        .attr("markerHeight", 4)
        .attr("orient", "auto")
        .append("path")
            .attr("d", "M 0,0 V 4 L6,2 Z"); //this is actual shape for arrowhead

    //d3.json(data, function(json) {
        var force = self.force = d3.layout.force()
            .nodes(data.nodes)
            .links(data.links)
            .distance(150)
            .charge(-1000)
            .size([w, h])
            .start();



        var link = vis.selectAll("line.link")
            .data(data.links)
            .enter().append("svg:line")
            .attr("class", function (d) { return "link" + d.value +""; })
            .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; })
            .attr("marker-end", function(d) {
                                                if (d.value == 1) {return "url(#arrowhead)"}
                                                else    { return " " }
                                            ;});


        function openLink() {
            return function(d) {
                var url = "";
                if(d.slug != "") {
                    url = d.slug
                } //else if(d.type == 2) {
                    //url = "clients/" + d.slug
                //} else if(d.type == 3) {
                    //url = "agencies/" + d.slug
                //}
                window.open("//"+url)
            }
        }




        var node = vis.selectAll("g.node")
            .data(data.nodes)
          .enter().append("svg:g")
            .attr("class", "node")
            .call(force.drag);


        node.append("circle")
            .attr("class", function(d){ return "node type"+d.type})
            .attr("r", function(d) { return radius(d.value) || 10 })
            //.style("fill", function(d) { return fill(d.type); })


        node.append("svg:image")
            .attr("class", function(d){ return "circle img_"+d.name })
            .attr("xlink:href", function(d){ return d.img_hrefD})
            .attr("x", "-36px")
            .attr("y", "-36px")
            .attr("width", "70px")
            .attr("height", "70px")
            .on("click", openLink())
            .on("mouseover", function (d) { if(d.entity == "company")
                                                {
                    d3.select(this).attr("width", "90px")
                                    .attr("x", "-46px")
                                    .attr("y", "-36.5px")
                                   .attr("xlink:href", function(d){ return d.img_hrefL});

                                                }
                })
            .on("mouseout", function (d) { if(d.entity == "company")
                                            {
                    d3.select(this).attr("width", "70px")
                                    .attr("x", "-36px")
                                    .attr("y", "-36px")
                                   .attr("xlink:href", function(d){ return d.img_hrefD});
                                            }
                });    


        node.append("svg:text")
            .attr("class", function(d){ return "nodetext title_"+d.name })
            .attr("dx", 0)
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .style("fill", "white")
            .text(function(d) { return d.name })
            .on("mouseover", function (d) { if(d.entity == "company"){
                    d3.select(this).text(function(d) { return d.full_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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
        });
    //});       

css:

@charset "utf-8";
/* CSS Document */

.link10 { stroke: #ccc; stroke-width: 3px; stroke-dasharray: 3, 3; }
.link1 { stroke: #000; stroke-width: 3px;}
.nodetext { pointer-events: none; font: 14px sans-serif; font-weight:bold;}

.node.type1 {
  fill:brown;
}
.node.type2 {
  fill:#337147;
}
.node.type3 {
  fill:blue;
}
.node.type4 {
  fill:red;
}

.node.type5 {
    fill:#1BC9E0;
}

.node.type6 {
    fill:#E01B98;
}

image.circle {
    cursor:pointer;
}

.fadein{
display:none;
font-size:20px;
}

.rectD{
background-color:#000000;
width:70px;
height:30px
}

.rectL{
background-color:#000000;
width:90px;
height:30px
}

Is it even possible to change the text after everything is loaded?

Please help

Answer

Dick Fox picture Dick Fox · Aug 30, 2013

Each node had an image and a text element associated with it. The mouseover events for the image and the text element were interfering with each other, since they occupy the same space.

I forked your jsfiddle and created a single mouseover listener for the node and to put both events in the same function:

        node.on("mouseover", function (d) {
            d3.select(this).select('text')
                .text(function(d){
                    return d.full_name;
                })
            if (d.entity == "company") {
                d3.select(this).select('image')
                    .attr("width", "90px")
                    .attr("x", "-46px")
                    .attr("y", "-36.5px")
                    .attr("xlink:href", function (d) {
                        return d.img_hrefL
                    });               
            }
        });

(there's a similar listener on node for mouseout to reverse these changes).