How to pick elements in d3 with a specific property value - javascript

I am having items painted using d3 on browser. I want to highlight some of them depending on their property. For example, I have groceries, soaps in which soap elements will have type as [for_bath (OR) for_cloth_wash]. I want to select those elements specific to for_bath in all soaps and groceries combined and painted together on same screen.
How ?
Also, my another doubt is document.getElementById() is not working inside d3's selections code. Am I true or an oversight ?
EDIT
var data = {"soaps":{"lux":"bath", "cinthol":"bath", "rin","cloth_washing"},
"shoes":{"valentine":"teens", "bootie":"kids", "kuuch":"kids"}};
// Now I want to show all bath soaps highlighted, may be with a circle around them.
var svg = d3.select("svg")
.selectAll(".items")
.data(data).enter()
.append("circle")
// highlighting styles
;
Here I want to select bath soaps and round them up.

You haven't given us any code, so I'm going to guess here. What you're probably looking for are CSS attribute selectors. So if you want to select elements which have the attribute soap set to for_bath, you would do
d3.selectAll("[soap=for_bath]");
This is for DOM elements only. If you're talking about data elements, then you can use the .filter() method:
data.filter(function(d) { return d.soap == "for_bath"; });
Regarding your second question, I'm not sure what you mean. The arguments to d3.select() or d3.selectAll() are DOM selectors, so document.getElementById() doesn't make sense here. You can however certainly use it other functions:
d3.selectAll("something").each(function() {
d3.select(this); // the current element
document.getElementById("something"); // another element
});

Related

Force Directed Graph, apply <line> style from nearest .on selector

StackBlitz demo - stackblitz is flaky in chrome, may not show preview. I use edge with stackBlitz, also fine on chrome for mobile.
I've created this force directed graph that has multiple labels attached to paths that sit on a <line>.
The label turns blue when individually clicked. What I have tried to do net is change the appearance of the <line> style depending on which label has been clicked. Each label has its own data, so I use an attribute in the data to determine what style the line should be upon .on click. Demo line 292:
d3.select(this).each(function(d){
if (d.lineStyle === "Confirmed"){
_d3.select('.link').style('stroke', '#444');
_d3.select('.link').style('stroke-dasharray', '0');
} else if (d.lineStyle === "Unconfirmed"){
_d3.select('.link').style('stroke-dasharray', '8, 5');
}
});
If lineStyle equals "confirm" apply one style or if lineStyle equals "Unconfirmed" show another style.
The issue with the above is it only applies the style to one line regardless of what label you click.
I need to find the nearest line to the label and apply the style to that line only.
I tried using this.parentNode something like _d3.select(this.parentNode).selectAll('.link').style('stroke-dasharray', '8, 5');
Is there a way I can find the nearest .link class in relation to the label maybe?
I have also seen a way to build a relationship function and call that somehow.
Firstly, that each inside the listener is unnecessary, since you have just one element being clicked.
The problem is that d3.select('.link') will simply select the first .link it finds on the page, top to down. So, the behaviour you have is expected.
What you probably want is filtering a line according to the text clicked. That could be done with parentNode, nextSibling etc., but that's not possible due to the structure you created. Thus, you can do it based on data:
const thisLine = linkEnter.filter(e => e.index === d.index);
Then:
if (d.lineStyle === "Confirmed"){
thisLine.style('stroke', '#444');
thisLine.style('stroke-dasharray', '0');
} else if (d.lineStyle === "Unconfirmed"){
thisLine.style('stroke-dasharray', '8, 5');
};
There's nothing in your code to revert the change, but that's trivial to do.
Here is the forked code: https://stackblitz.com/edit/github-dzry6q-6vj5yx?file=src%2Fapp%2Fdirected-graph-experiment.service.ts,src%2Fapp%2Fapp.component.ts

Nightwatch dropdowns handling by passing value

Below is the approach I have used in order to select values from a dropdown using nightwatch.As you can see this is not a good approach. We can't select the specific value from dropdown unless we click on the exact element.
this.useXpath();
this.click('(//td[#class="styles_selectDropdownContainer__2Vrns"])[1]')
this.useCss();
this.click('#react-select-6-option-1')
In selenium java there is a very good option like below
Select fruits = new Select(driver.findElement(By.id("fruits")));
fruits.selectByVisibleText("Banana");
I want to know of there is a similar approach can be used in nightwatch as well?
This is not built up using Select and Option tag so inbuilt selenium functions wouldn't work. Work around would be to click first on the parent span and then in list store every div (which is option), iterate the loop and for each web element if text matches with your desired text you can click on it.
Code :
this.useCss();
this.click("span[aria-live='polite']")
Now store options in a list :
var elements = document.querySelectorAll('.elements'); // use
//div[contains(#class,'option')] as element selector.
Now iterate the list :
// Iterate over them.
[].forEach.call(elements, function (element) {
// Manipulate each element.
element.click();
});
});

How to get ids of hidden nodes

it's possible to get hidden nodes or edges??
i tried to get by making a filter but it doesn't work becaus there is no property hidden in edges dataset.
Thanks.
var HidenEdgesIds = edges.getIds({
filter: function (item) {
return ((item.hidden == true);
}
});
this is a part of my code.
Based on the documentation of DataSets and Edges something like that should work (untested):
var hiddenEdgeIds = edges.getIds({
filter: function (item) {
return item.hidden == true;
}
});
Update
Do you set the hidden property, when you add the edges to your dataset?
Hidden nodes are... hidden. It's something used internally in the Network to render beautifully curved edges.
Why do you need access to the hidden nodes?
UPDATE: if I understand you correctly you have two types of nodes, one of which you can toggle to be displayed or hidden. To achive that, you can simply create your nodes with ids you choose, and to show/hide them update the nodes hidden property. You should not try to use the internally used hidden nodes, but simply create your own group with nodes that you toggle visible/hidden.

How can insert order of an enter selection be controlled?

I have an enter selection with two elements that I want to prepend to a svg container such that the order of the two elements is maintained. I have tried using insert using the :first-child selector like this
var newlayers = layer.enter();
newlayers.insert("g",":first-child")
As a result of using the :first-child selector the second element in the enter selection ends up being the first element in the svg container after insertion. How can I avoid this behavior?
Ok I was able to reorder the elements using .sort after the insert selection is created in this way:
var newlayers = layer.enter();
newlayers.insert("g",":first-child")
.sort(function(a,b){ return b-a; });
This leaves the ordering of the data intact while only reordering the inserted elements in DOM. I went down the route of reordering the data returned on enter() itself and that opened a whole new bunch of other problems.

How to add back to DOM an existing D3 SVG chart?

Hi have a D3 SVG object:
d3.select("#chart").append("svg")
.attr('id', 'chartId' + idx)
To which I append rects to create a bar chart.
I would like to be able to add and remove it from the DOM.
I am able to remove it easily with:
d3.select('svg#chartId' + j).remove();
How can I re-append the entire SVG chart I just removed?
D3 doesn't support reattaching nodes that have been deleted.
selection.remove() doesn't completely destroy the node though, it acts quite similarly to jQuery's detach() method. (Using jQuery with SVG elements never ends well)
The good news is that this is pretty easy with the built-in SVG DOM.
// .remove() returns the detached node.
var el = d3.select('.selection').remove();
var nativeEl = el[0][0];
nativeEl.parentNode.appendChild(nativeEl);
Usually it would probably just be easier to show and hide these elements, but in cases like re-arranging the order of elements post-render, this can be pretty useful.
Use detach() instead of remove()
var refToElelment = $(d3.select('svg#chartId' + j)).detach();
OR
$('#chartId' + j).detach()
Later..
$('#target').append(refToElelment);

Categories

Resources