Using selectAll in d3.js - d3.js

I would like to selectAll X that have the properties Y and Z. For instance, I would specifically like to select all lines with an ID of d.id AND a target of d.target. It's the 'and' part that I can't figure out; I assumed from the documentation that it should be something like this:
selectedLine = d3.selectAll("line[id="+d.id+"]").selectAll(line[target="+d.target+"]");
But calling selectAll on a selection always returns an empty selection to me, regardless of the contents (In this case, I'm certain that exists one line with an ID of d.id and a target of d.target).

I suspect that target is not an attribute that the line element but a data property instead. Besides that, calling selectAll on a selection does not return an empty selection: you probably have some other problem. Finally, pay attention to the fact that you are using selectAll with an ID, which makes little sense: IDs have to be unique.
Anyway, whatever you are using in those attribute selectors, you can simply use multiple attribute selectors:
selectedLine = d3.selectAll("line[id='foo'][target='bar']")
According to the documentation:
Multiple attribute selectors can be used to refer to several attributes of an element, or even several times to the same attribute.
Here, the selector matches all SPAN elements whose "hello" attribute has exactly the value "Cleveland" and whose "goodbye" attribute has exactly the value "Columbus":
span[hello="Cleveland"][goodbye="Columbus"]

Related

Get group from D3js selectAll in console?

In the context of understanding better the details of D3.js, I am a bit puzzled how selectAll works.
For example, based on this codepen, it is possible to write:
vis.selectAll("circle.nodes")
or:
vis.selectAll("my_own_tag_group")
But after the D3js code is executed, I would expect that the selectAll gives a group that I could access from the web console too:
document.getElementsByClassName('my_own_tag_group')
HTMLCollection [ ] (empty)
What am I missing from the explanations given in http://bost.ocks.org/mike/selection/
At least from your code, it looks like you're doing the selection wrong. selectAll follows CSS3 selector rules:
D3 uses CSS3 to select elements. For example, you can select by tag ("div"), class (".awesome"), unique identifier ("#foo"), attribute ("[color=red]"), or containment ("parent child"). Selectors can also be intersected (".this.that" for logical AND) or unioned (".this, .that" for logical OR). If your browser doesn't support selectors natively, you can include Sizzle before D3 for backwards-compatibility.
Therefore, you'd probably want to use
vis.selectAll(".my_own_tag_group")
if it refers to a class, and
vis.selectAll("#my_own_tag_group")
if it refers to an id (which might either make sense or not).
If it refers to something else, you might want to restructure it so that it refers to a class.

How to select a node based on its child's text value?

I want to select a node based on the text value of a child.
My structure is as follows (sorry for german nodes):
<InspizierteAbwassertechnischeAnlage>
<Objektbezeichnung>10502002</Objektbezeichnung>
<Anlagentyp>1</Anlagentyp>
</InspizierteAbwassertechnischeAnlage>
How can I select the <InspizierteAbwassertechnischeAnlage> node where e.g. <Objektbezeichnung> = 10502002?
Why your solution didn't work
ancestor:://*[text()='10502002'] is syntactically incorrect, it's not valid XPath. I'm not sure what you tried to do with the axes here.
//*[text()='10502002'] itself would just select the Objektbezeichnung itself and not its parent. It would also select any other element with such a value, regardless of its name. In case of this document, nothing redundant would be returned but you have to be careful when using wildcards (*)
The solution
It's quite simple, you have to use a predicate to inspect the content of the child element
//InspizierteAbwassertechnischeAnlage[Objektbezeichnung = '10502002']
Note the double slash (// ), it is the abbreviated syntax for the descendant-or-self axis. The above expression translates to:
/descendant-or-self::InspizierteAbwassertechnischeAnlage[Objektbezeichnung = '10502002']
Or in plain English
In the set of all descendants of the document's root, find InspizierteAbwassertechnischeAnlage elements that contain at least one Objektbezeichnung element with a value of 10502002
As for German element names, at least it's not Hottentottenstottertrottelmutterbeutelrattenlattengitterkofferattentäter or Rhababerbarbarabarbarbarenbartbarbierbierbarbärbel

Selenium find element which have no attributes but have parents with same attributes

I am trying to find XPath of an element which has no attribute. It can only be identified by its parent's attribute. However, the parent also does not have unique attribute.
Eg: //*[#id="btn"][1]/ul/li[2]/a/span
Here there are 2 elements with id=btn. How do i get the 2nd element. The above syntax gives me 1st element.. However if i use:
//*[#id="btn"][2]/ul/li[2]/a/span
I get an error message
"The xpath expression '//*[#id="btn"][2]/ul/li[2]/a/span' cannot be evaluated or does not result in a WebElement "
Try this, you select those two first, then use brackets around and index them.
(//*[#id="btn"]/ul/li[2]/a/span)[2]
By the way, it's not a good practice to have multiple elements sharing same ids, if you are the developer, may consider change them.

collect all xpath results into an array in ruby

I have a very poorly coded JSP that I am trying to run automation on. There are a series of checkboxes with names (no IDs) of "delete[x]" where X is the item number of the item populated. I am trying to select all the checkboxes so I can delete every entry. Here is what I have
check_boxes = []
check_boxes.push(#browser.checkbox(:xpath, "//input[contains(#name,'delete')]"))
puts check_boxes.size
check_boxes.each do |check_box|
check_box.set
The problem with this is it only selects the first instance (node) that matches the xpath to dump into the array. I know I can iterate through the xpath adding an index to the node, and then put a rescue in that drops me out when the index goes out of bounds, but that seems like the dirty way to do it.
I know there is an "as" tag that gets a set of anchors and i was wondering if there was a method like that for taking the whole selection of checkboxes
I don't think the problem is the xpath itself. It is the #browser.checkbox that is causing only the first checkbox to be returned.
If you want all matching checkboxes, you should use (notice the plural):
#browser.checkboxes
Note that checkboxes returns a collection of checkboxes. Unless you are doing something really fancy, you usually do not need to convert it to an array.
You can simply do:
#browser.checkboxes(:name => /delete/).each do |checkbox|
checkbox.set
end

Prototype $$ returns array, should return one element like $

When using the dollar-dollar-function in prototype I alway get an array of elements back, instead of just one element with the dollar-function. How can I combine the power of CSS-selectors of $$ but still get only one element back?
Changing the structure of the source is not possible, so I can't just select it with the id. It needs to get selected with CSS, but should just return one element.
You can also do
$$('.foo').first()
It looks cleaner than $$('.foo')[0] for my taste :)
It does not make sense to return a single element when selecting by class name because potentially there could be many elements in the DOM that have this class. So you could always use the first element of the returned array if you are sure that it will be unique.
$$('.foo')[0]

Resources