There are two other technical reasons for not supporting ascension via
method chaining.
First, any subselection would have to keep a reference to the parent
selection that generated it, which is potentially a bit of extra
baggage. It might also be possible for the two to get out of sync.
Second, it gets more complicated with grouping. When you subselect
with selectAll, you group a selection: for each element in the current
selection, you select an array of child elements, and each of these
arrays becomes a separate group. Separate groups are needed to bind
different hierarchical data (such as multi-dimensional arrays) to each
group. It's also handy for assigning indexes within a group rather
than globally. If you want to go back up the hierarchy by selecting a
parent node, you have to decide whether you want to select the parent
for each element (in which case the same parent node may be selected
multiple times for siblings), or for each group.
It's just easier to use variables. You don't have to create a variable
for everything; only those cases where you want to append multiple
siblings, or bubble back up to a parent after modifying children. And
yes, I believe this also encourages you to make your code more
readable by naming what you are doing. :)
Mike
http://www.w3.org/TR/html5/apis-in-html-documents.html#insertadjacenthtml
For example, perhaps there's an "adjoin" operator which takes one of
the four placement options. In this case, we want to insert a sibling
appearance element after the box element:
svg.append("shape")
.append("box")
.adjoin("appearance", "afterend")
.append("material")
.attr("diffuseColor", "red");
The name "adjoin" might be a bit awkward, but I think it's important
it's not "append" or "insert" so that it sticks out when reading the
structure. Of course, using local variables makes the structure even
more obvious. ;)
Mike
This is already available as selection.call:
https://github.com/mbostock/d3/wiki/Selections#wiki-call
For example:
d3.select("body")
.call(function(body) { body.append("h1").text("hello"); })
.call(function(body) { body.append("p").text("world"); });
Personally, I find deeply-nested method chaining a bit hard to follow
and prefer local variables. But call is there if you want to use it.
You can also pass additional arguments, e.g.,
d3.select("body")
.call(heading, "hello")
.call(paragraph, "world");
function heading(parent, text) {
parent.append("h1").text(text);
}
function paragraph(parent, text) {
parent.append("p").text(text);
}
Mike