var dispatch = d3.dispatch( "legendMouseover" ) // This creates the object that will be dispatched on mousing over the legends.
// Draw individual hyper text enabled bars...canvas.selectAll("rect")
.data(dataSet).enter().append("svg:a") // Append legend elements .attr("xlink:href", function(d) { return d.link; }).append("svg:rect").attr("x", function(d, i) { return x(i); }).attr("y", function(d) { return canvasHeight - y(d.magnitude) + 15; }).attr("height", function(d) { return y(d.magnitude); })
.attr("width", barWidth).style("fill", function(d, i) { colorVal = colorScale(i); return colorVal; } ).attr("color_value", function(d, i) { return colorScale(i); }) // Bar fill color....style("stroke", "white") // Bar border color...
.dispatch.on('legendMouseover', barMouseoverFunction); // This will call the bar color changing function "barMouseOverFunction" when it receives the dispatched Event Object.
var barMouseOverFunction = function() {
var bar = d3.select(this);bar.style("fill", "Maroon" );
};
.on('mouseover', dispatch.legendMouseover()); // This
I would only use d3.dispatch if you want to abstract some native event
sequence into higher-level events, such as how the d3.svg.brush
component translates a mousedown, mousemove and mouseup event sequence
(or likewise touchstart, touchmove, touchend) into brushstart, brush
and brushend.
Getting to your code:
> .on('mouseover', dispatch.legendMouseover());
Read this line closely. What you are doing first is calling
dispatch.legendMouseover. This will invoke all the "legendMouseover"
listeners, as described here:
https://github.com/mbostock/d3/wiki/Internals#wiki-dispatch
Then, you are taking the return value of this function call and
assigning that as the mouseover listener. The return value is, in
fact, undocumented! (I'll fix that.) However, if you look at the
implementation [1], you can see it is the dispatch object. This is an
object, not a function, so you'll get an Error in the console whenever
you mouseover.
If you intended to notify the "legendMouseover" listeners on
mouseover, then you must remove the parens, so that you're passing the
function to selection.on, rather than calling it:
.on("mouseover", dispatch.legendMouseover)
However, I don't see a strong reason to use a custom event here, when
your listeners could listen to the mouseover events directly.
Mike
[1] https://github.com/mbostock/d3/blob/master/src/core/dispatch.js#L30-37
I. Mouseover an Arc/Bar and...
1) have that Arc change fill color, and2) have its corresponding bullet change fill color, and3) have it's corresponding Legend Text change fill color
II. Mouseover a Legend Bullet and...1) have that Legend Bullet change fill color, and
2) have its corresponding Arc/Bar change fill color, and3) have it's corresponding Legend Text change fill colorIII. Mouseover Legend Text and...1) have that Legend Text change fill color, and
2) have its corresponding Legend Bullet change fill color, and3) have it's corresponding Arc/Bar change fill color
Break the larger problem into smaller problems. First: how would you
do the above? Given some way of identifying a set of related elements
(arc, legend, etc.), how would you select them and change their
appearance. Second: how can you trigger this changed based on a user
event, such as mouseover?
One method would be to give each related element a class. For example,
perhaps you would use the class "type-apple" for all the elements that
pertain to apples, while the elements that pertain to oranges have the
class "type-orange". The "type-" prefix serves only to avoid a name
collision with other classes you might use for styling. You can now
write a method that takes a type (a string, either "apple" or
"orange") and selects the related elements:
function highlight(type) {
d3.selectAll(".type-" + type)…
}
Of course, you might want to do different things for your legend
elements versus your arcs or bars. So you can make multiple more
specific selections:
function highlight(type) {
d3.selectAll(".legend.type-" + type)…
d3.selectAll(".arc.type-" + type)…
d3.selectAll(".bar.type-" + type)…
}
And of course, when you create the elements on initialization, you
must remember to give them the appropriate dynamic class name. For
example:
g.append("path")
.attr("class", function(d) { return "arc type-" + d.type; })
.attr("d", …)
…
This requires, of course, that the `type` property be resolved as a
single class name, and that it's unique across the types. You can't
use a name with spaces in it, for example. Sometimes, the easiest
thing to do is to use the index (0, 1, 2, 3, etc.) as a unique
identifier rather than using a human-readable name.
Once you've implemented the desired highlight behavior, you can enable
it on mouseover by accessing the data. For example:
g.append("path")
.attr("class", function(d) { return "arc type-" + d.type; })
.attr("d", …)
.on("mouseover", function(d) { highlight(d.type); })
…
In fact, if you want to be clever, you can pass the data directly to
the highlight function. And then you can use the same mouseover
function for all of your elements:
function mouseover(d) {
d3.selectAll(".legend.type-" + d.type)…
d3.selectAll(".arc.type-" + d.type)…
d3.selectAll(".bar.type-" + d.type)…
}
g.append("path")
.attr("class", function(d) { return "arc type-" + d.type; })
.on("mouseover", mouseover)
…
g.append("rect")
.attr("class", function(d) { return "bar type-" + d.type; })
.on("mouseover", mouseover)
…
You'll probably also want to define a mouseout (or `unhighlight`)
function, or allow the mouseover function to take null. In this case,
you'll revert the appearance of any highlighted elements.
Mike
".attr("class", function(d, i) { return "arc.type-" + d.recordID; })
Set #1: ("arc.type-record_1", "legendBullet.type-record_1", "legendText.type-record_1")
Set #2: ("arc.type-record_2", "legendBullet.type-record_2", "legendText.type-record_2")Set #3: ("arc.type-record_3", "legendBullet.type-record_3", "legendText.type-record_3")Etc.
Set #1: (arc-index-1, legendBullet-index-1, legendText-index-1)Set #2: (arc-index-2, legendBullet-index-2, legendText-index-2)Set #3: (arc-index-3, legendBullet-index-3, legendText-index-3)Etc.
Set #1: (pie1-arc-index-1, pie1-legendBullet-index-1, pie1-legendText-index-1)Set #2: (pie2-arc-index-2, pie2-legendBullet-index-2, pie2-legendText-index-2)Set #3: (pie3-arc-index-3, pie3-legendBullet-index-3, pie3-legendText-index-3)Etc.
Set #1: (chart1-arc-index-1, chart1-legendBullet-index-1, chart1-legendText-index-1)Set #2: (chart1-arc-index-2, chart1-legendBullet-index-2, chart1-legendText-index-2)Set #3: (chart1-arc-index-3, chart1-legendBullet-index-3, chart1-legendText-index-3)Etc.
Set #1: (chart2-arc-index-1, chart2-legendBullet-index-1, chart2-legendText-index-1)Set #2: (chart2-arc-index-2, chart2-legendBullet-index-2, chart2-legendText-index-2)Set #3: (chart2-arc-index-3, chart2-legendBullet-index-3, chart2-legendText-index-3)Etc.
Set #1: (chart3-arc-index-1, chart3-legendBullet-index-1, chart3-legendText-index-1)Set #2: (chart3-arc-index-2, chart3-legendBullet-index-2, chart3-legendText-index-2)Set #3: (chart3-arc-index-3, chart3-legendBullet-index-3, chart3-legendText-index-3)Etc.
Hi, Mike: