----------------------------------------------------------
Show / hide an element by clicking on another element
This is a trick that I found I wanted to implement in order to present a graph with a range of lines and to then provide the reader with the facility to click on the associated legend to toggle the visibility of the lines off and on as required.
The example we’ll follow is our friend from earlier, a slightly modified example of the graph with two lines.
Show / hide lines on a graph |
In this example we will be able to click on either of the two titles at the bottom of the graph (‘Blue Line’ or ‘Red Line’) and have it toggle the respective line and Y axis.
THE CODE
The code for the example is available online at bl.ocks.org or GitHub. It is also available as the file ‘show-hide.html’ as a separate download with D3 Tips and Tricks. A copy of most the files that appear in the book can be downloaded (in a zip file) when you download the book from Leanpub.
There are two main parts to implementing this technique. Firstly we have to label the element (or elements) that we wish to show / hide and then we have to give the object that will get clicked on the attribute that allows it to recognize a mouse click and the code that it subsequently uses to show / hide our labelled element.
Labeling the element that is to be switched on and off is dreadfully easy. It simply involves including an
id
attribute to an element that identifies it uniquely.svg
.
append
(
"path"
)
.
attr
(
"class"
,
"line"
)
.
attr
(
"id"
,
"blueLine"
)
.
attr
(
"d"
,
valueline
(
data
));
In the example above we have applied the
id
blueLine
to the path that draws the blue line on our graph.
The second part is a little trickier. The following is the portion of JavaScript that places our text label under the graph. The only part of it that is unusual is the
.on("click", function()
section of the code.svg
.
append
(
"text"
)
.
attr
(
"x"
,
0
)
.
attr
(
"y"
,
height
+
margin
.
top
+
10
)
.
attr
(
"class"
,
"legend"
)
.
style
(
"fill"
,
"steelblue"
)
.
on
(
"click"
,
function
(){
// Determine if current line is visible
var
active
=
blueLine
.
active
?
false
:
true
,
newOpacity
=
active
?
0
:
1
;
// Hide or show the elements
d3
.
select
(
"#blueLine"
).
style
(
"opacity"
,
newOpacity
);
d3
.
select
(
"#blueAxis"
).
style
(
"opacity"
,
newOpacity
);
// Update whether or not the elements are active
blueLine
.
active
=
active
;
When we click on our ‘Blue Line’ text element the
.on("click", function()
section executes.
We’re using a short-hand version of the
if
statement a couple of times here. Firstly we check to see if the variable blueLine.active
is true or false and if it’s true it gets set to false and if it’s false it gets set to true (not at all confusing). var
active
=
blueLine
.
active
?
false
:
true
,
newOpacity
=
active
?
0
:
1
;
Then after toggling this variable we set the value of
newOpacity
to either 0 or 1 depending on whether active
isfalse
or true
(the second short-hand JavaScript if statement).
We can then select our identifiers that we have declared using the
id
attributes in the earlier pieces of code and modify their opacity to either 0
(off) or 1
(on) d3
.
select
(
"#blueLine"
).
style
(
"opacity"
,
newOpacity
);
d3
.
select
(
"#blueAxis"
).
style
(
"opacity"
,
newOpacity
);
Lastly we update our
blueLine.active
variable to whatever the active
state is so that it can toggle correctly the next time it is clicked on. blueLine
.
active
=
active
;
Quite a neat piece of code. Kudos to Max Leiserson for providing the example on which it is largely based in an answer to a question on Stack Overflow.
The description above (and heaps of other stuff) is in the D3 Tips and Tricks book that can be downloaded for free (or donate if you really want to :-)).
Demo is pointing to a wrong one.
ReplyDeleteYikes! Many thanks for point this out. It will be the same in the book as well. Fixed in the post above now and the revised edition of the book will be available in half an hour. Thanks again.
DeleteI'm not sure if title correctly shows article content. People are moved here from google and they more want to look at D3 pattern for hidding / showing simple divs...
ReplyDeleteHmm.... Interesting observation. Do you have an alternative suggestion?
DeleteWhat If I want to set a dynamic Id in active function to check whether its active and assigning it back the value of active to it. For example I have four lines in my graph and each created different Ids. I want to check the user clicked line id and set to active(true and false). I tried doing the same but its not working. It works only with static values I guess. Could you give me any workaround for the same?
ReplyDeleteIt sounds a little bit like what I explain in the post here http://www.d3noob.org/2014/07/d3js-multi-line-graph-with-automatic.html You can check out a live version here http://bl.ocks.org/d3noob/e99a762017060ce81c76
DeleteThis is actually one of my favourite graphs, just because I worked out how to dynamically assign id's. (I'm a slow learner :-)).
Whats the .active variable? Is it a custom attribute or in built d3 selection attr ? Please clarify.
ReplyDeleteIt's just a variable and the name is purely descriptive (i.e, we could call it anything). I'ts only role is to toggle between true and false. to test this (because I haven't, and it's been a loooong time since I did this example) try changing the variable name to something different.
DeleteI have lines with a tooltip and I am able to hide the lines but the tooltips do no go away so all I am left with is a graph with dots. I was wondering if you know a way to fix that?
ReplyDeleteAhh... Very good. What you would need to do is to change the opacity of all the objects associated with the legend label that is clicked on. To do that I think that you would need to have the tooltips associated with the line and use a selectall statement instead of a select. This might need a bit of experimentation. Good luck
Delete