By pushing a node button in d3 with a button outside svg

I created a force-oriented graph using D3 and displaying the node identifier in a normal div. I need to highlight the node whose id was clicked in the div. I searched for the node identifier and using plain javascript tried to click it, but it does not work.

+22
javascript force-layout
Jun 26 2018-12-12T00:
source share
2 answers

In general, if a user interacts with element A, how do you select (and then modify) related elements of B? There are many ways to achieve this, but there are three general approaches.

Option 1. For one-to-one comparisons, select by id.

If each element in has exactly one corresponding element in B, you can select the associated element B by id, for example d3.select("#foo") to select <div id="foo"> .

This approach requires setting an identifier for each item in B using selection.attr . This is easiest if your data has a built-in unique identifier, for example d.name or d.id :

 b.attr("id", function(d) { return d.id; }); 

Then, to enable click on elements A to change the fill color of the corresponding element in B, use selection.on to register, click the listen button, and then select by id:

 a.on("click", function(d) { d3.select("#" + d.id).style("fill", "red"); }); 

Identifiers must be unique and valid . For example, an identifier must begin with a letter, not a number, and cannot contain spaces. If your data does not yet have a unique identifier, you can create it from an index, for example

 b.attr("id", function(d, i) { return "b-" + i; }); 

And later, assuming that the elements of A are in the same order,

 a.on("click", function(d, i) { d3.select("#b-" + i).style("fill", "red"); }); 

You can also iterate over your dataset to create a unique identifier.

Option 2. For one-to-many comparisons, select by class.

To select elements of the "foo" class, such as <div class="foo"> , say d3.selectAll(".foo") . Use this approach if an element from A matches several elements in B. For example, if you have a force-oriented graph showing relationships between students, you can color the nodes based on each student year, and then use the legend to switch visibility every year.

As in the previous approach, you can use selection.attr to set the "class" attribute. In this case, the class attribute is not unique, so it can come from the d.type property in the data:

 b.attr("class", function(d) { return d.type; }) 

If you have several legends for different categorical data attributes, you can also be more specific and class name prefix. To continue the student year example:

 b.attr("class", function(d) { return "year-" + d.year; }) 

Setting a class attribute will replace all previously installed classes, so if you want to apply several classes to elements, you need to combine them with a space when setting the class attribute.

Then, to enable click on elements A to change the fill color of the corresponding elements in B, use selection.on to register a click listener, and then select by class:

 a.on("click", function(d) { d3.selectAll("." + d.type).style("fill", "red"); }); 

Note that here we use selectAll instead of select ; because we want to select all the relevant elements, not just the first one. Again, you need to make sure that the class attribute is valid .

Option 3. For everything else, select and filter the data.

The previous two approaches generate identifiers and classes so that the browser can index elements in B for efficient selection. For a small number of items, or when more general selection methods are required, you can omit the id or class attributes and just manually select selection.filter .

Let us name the binding associated with each element in da , and the binding to each element in B db . Now all we need to do is define an expression that returns true when da matches db . For example, if we want to filter by type:

 a.on("click", function(da) { b.filter(function(db) { return da.type == db.type; }).style("fill", "red"); }); 

The first two options are preferable, but manual filtering is sometimes convenient, for example, when you have a range slider and want to filter based on a quantitative variable.

+73
Jun 26 2018-12-12T00:
source share

When you write:

... and using normal javascript tried to click it ...

what do you mean?

If you mean that you wrote code like:

 mySVGElement.click(); 

then this is your problem. Not all DOM elements have a click() method, such as <button> or <input…> . Instead, you need to simulate and fire your own click event :

 function simulateClick(elementToClick){ var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); var canceled = !elementToClick.dispatchEvent(evt); return canceled; //Indicate if `preventDefault` was called during handling } 
+4
Jun 26 2018-12-12T00:
source share



All Articles