select rectangle id

658 views
Skip to first unread message

Rick Otten

unread,
Apr 6, 2011, 3:01:57 PM4/6/11
to d3...@googlegroups.com
When I assign an id to an SVG rectangle, I was hoping I would then be able
to select it. That doesn't seem to be working for me.

Should it work?

I had hoped that rather than doing a transition to my entire set of
rectangles, I could transition just some of them by using 'select' on
their id values.

Then I could do things like highlighting, or moving, or resizing a subset
of rectangles when the user pushes a button without having to redo all of
them via a global .selectAll("rect").


I tried prefacing the id name with a hash, like I do for buttons and table
elements, but that didn't do it either.


building the rectangle:

.append("svg:rect")
.attr("id", "myRectangle")

I can see the id on the SVG object when I look at the svg source.

Then I tried:

d3.selectAll("myRectangle")
d3.selectAll("#myRectangle")

Both return empty sets.

I'm not confident enough with D3 yet to know whether something isn't
working, or whether it isn't supposed to work.

--
Rick Otten
rot...@windfish.net
O=='=+


Nelson Minar

unread,
Apr 6, 2011, 6:37:25 PM4/6/11
to d3...@googlegroups.com, Rick Otten
On Wed, Apr 6, 2011 at 12:01 PM, Rick Otten <rot...@windfish.net> wrote:
When I assign an id to an SVG rectangle, I was hoping I would then be able to select it.  That doesn't seem to be working for me.

That should absolutely work. I did a very simple example similar to what you are trying, you can see it at http://bl.ocks.org/906688. Does it work for you?

d3.selectAll("#myRectangle") should return a data structure that looks like [ Array[1] ] in the Chrome debugger.

Mike Bostock

unread,
Apr 6, 2011, 7:43:45 PM4/6/11
to d3...@googlegroups.com, Rick Otten
Not all browsers support case-sensitive IDs. I would recommend using
all lowercase. If you want to separate words, an underscore (_) is a
safe choice.

Mike

Rick Otten

unread,
Apr 7, 2011, 9:45:31 AM4/7/11
to d3...@googlegroups.com
Browser version is probably at least part of my problem.

Nelson's example renders a rectangle just fine in Firefox 4.0. It does
not render anything in the Firefox 3.5.7 that I and most of my users are
officially stuck with.

I can see with firebug that the SVG in his example is getting the fill
style correctly updated. Nothing ever draws though.

So I messed with the SVG construction to get Nelson's example to try to
get it to draw a rectangle in my older Firefox.

After some experimentation it appears that although the older Firefox
version updates the SVG after you select it, it never draws it. The only
way to get the older browser to draw the SVG (that I found) is to select
"body" instead, and then append a fresh SVG to the body, and then append
the rectangle to that. [ Even though inspection in firebug shows exactly
the same resultant text as Nelson's example. ]

When I do that, I can see the rectangle color change based on the id
selection even in my older browser.

d3.select("body")
.append("svg:svg")


.append("svg:rect")
.attr("id", "myRectangle")

.attr("width", "100")
.attr("height", "100")
.style("fill", "red");

So, now I'm back to beating my head on my original, more complicated code
to figure out why the selections weren't working... At least now I know it
is supposed to work.


ps: wrapping the select with a timeout in that example lets you see it
switch from red to blue. Otherwise the transition is too fast and it just
looks blue...

setTimeout(function() {d3.selectAll("#myRectangle").style("fill",
"blue");}, 3000);


Thanks for your help!

Nelson Minar

unread,
Apr 7, 2011, 10:25:48 AM4/7/11
to d3...@googlegroups.com, Rick Otten
On Thu, Apr 7, 2011 at 6:45 AM, Rick Otten <rot...@windfish.net> wrote:
Nelson's example renders a rectangle just fine in Firefox 4.0.  It does not render anything in the Firefox 3.5.7 that I and most of my users are officially stuck with.

That's odd. So Firebug in 3.5 is showing you the DOM SVG nodes exist, but it's not drawing them? Maybe 3.5 had some problem where it doesn't re-render after DOM updates? Your initial problem was that selectAll() wasn't returning the nodes at all. Sounds like my example has a different problem in your browser.

I made a small change to the example, if you want to retry it in Firefox 3.5.7.. I put all the code in an onload() handler instead of inline. I've honestly never understood why all the D3 examples work without waiting for the load event.

Rick Otten

unread,
Apr 7, 2011, 10:43:51 AM4/7/11
to d3...@googlegroups.com
Nope. That doesn't work in 3.5.7 either.

In fact it seems to be worse in that the fill in the hidden SVG never
changes to blue either.

Your new example does work nicely in FF 4.

I'll try it in other browsers when I get a chance. I'm going to pursue
getting us all an official FF upgrade so I don't have to worry about it so
much.

Fewer than 0.1% of our customers are still using FF 3.5.7. (Google apps
don't support it any more either.)

Mike Bostock

unread,
Apr 7, 2011, 11:59:41 AM4/7/11
to d3...@googlegroups.com, Rick Otten
Alright, so a few confounding factors here.

First, `console` is not supported in Firefox. If you put `console.log`
in an example for Firefox, it will crash, even if everything else
works!

Second, you can't define a bare <svg> element in HTML, because it's in
the wrong namespace. If you use XHTML, it's possible to embed an
<svg:svg> element under certain circumstances, but it's hard to get it
to work reliably. You should create the SVG element using d3's
`append("svg:svg")`.

Third, you need to set a width & height for SVG elements. Some
browsers have default width & height, while others do not.

Fourth, case-sensitive IDs are not recommended.

This forked example works for me in FF 3.6, which is the oldest version I have:

http://bl.ocks.org/908051

Mike

Rick Otten

unread,
Apr 7, 2011, 12:30:40 PM4/7/11
to d3...@googlegroups.com
And that version works in FF 3.5.7 too.
:-)

Thanks Mike.

Nelson Minar

unread,
Apr 7, 2011, 2:48:05 PM4/7/11
to d3...@googlegroups.com
Just goes to show; the way to get the right answer to a question is post the wrong answer to the Internet and wait to be corrected. Sorry for the misdirection and thanks for the corrections, Mike. I updated my gist; now it's basically the same.

If I may hijack the thread... how come the D3 examples work without waiting for the load event? Is it just luck the <body> tag is there before the script runs?


Notes below are from my own research trying to really understand what's going on:

Second, you can't define a bare <svg> element in HTML, because it's in the wrong namespace.

I think some modern browsers let you get away without the SVG namespace, but it's not correct. Chrome confuses things in that the debugger UI doesn't show the namespace on the SVG nodes D3 creates. The D3 code d3.ns.qualify() has the details of what namespaces D3 manages for us. More reading:
 
Fourth, case-sensitive IDs are not recommended.

The HTML 5 spec implies they should work and be case sensitive, but it'd be foolish to rely on that.


Mike Bostock

unread,
Apr 7, 2011, 5:00:48 PM4/7/11
to d3...@googlegroups.com, Nelson Minar
> If I may hijack the thread... how come the D3 examples work without waiting
> for the load event? Is it just luck the <body> tag is there before the
> script runs?

The <script> is embedded inside the <body>; therefore the body is
guaranteed to exist. The DOM isn't fully constructed yet (whatever's
after the script does not yet exist), but that's fine for our
purposes.

Generally speaking you only need to wait for the load event (or
similarly the ready event) if you want to guarantee that the browser
has computed the flow layout, including any external resources such as
images and stylesheets. Or, you want to make global changes (e.g.,
selectAll("p")) that depend on the complete document.

Mike

Reply all
Reply to author
Forward
0 new messages