Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to externally trigger d3 events

I have a d3 selection upon which I have defined event callbacks.

var obj = d3.select("#kk").on("mouseleave",function(){
              console.log("mouse leave");       
          });

How can I trigger the event externally? Is there something like:

obj.mouseleave(); // actuall mouse leave function calling

If there is, and if I select the object without referring to obj, will the trigger still work?

As in:

var newObje=d3.select("#kk");
newObje.mouseleave(); //will this trigger the previously defined instructions
like image 612
S.Dan Avatar asked Nov 04 '16 04:11

S.Dan


3 Answers

If you are already on D3 v4, you can use selection.dispatch() which was specifically designed to do exactly what you are looking for:

# selection.dispatch(type[, parameters]) <>

Dispatches a custom event of the specified type to each selected element, in order.

This was included in v4 as a result of the issue "Ability to trigger event handlers manually. #100".

Furthermore, the method will enable you to dispatch events of the same type to all elements contained in the selection. The implementation of that method looks similar to the approach the other answerers took by putting event.dispatch() to use, but will make your life somewhat easier. The following snippet has a listener for each individual circle, which may all be triggered by the button at once.

var circles = d3.select("svg").selectAll("circle")
  .data(d3.range(5))
  .enter().append("circle")
    .attr("cx", function(d, i) { return 60 * i + 20; })
    .attr("cy", "30")
    .attr("r", "20").attr("fill", "blue")
    .on("mouseleave",function(){
      d3.select(this)
        .attr("fill", "red")
        .transition().duration(1000)
        .attr("fill", "blue");
    });

d3.select("#btn")
  .on("click", function() {
    circles.dispatch("mouseleave");
  });
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="400" height="70"></svg>

<button id="btn">Dispatch mouseleave to all circles</button>
like image 106
altocumulus Avatar answered Nov 04 '22 23:11

altocumulus


Yes, you don't need d3 to trigger the event, vanilla javascript is enough for that. You simply need to use the dispatchEvent function.

Here is an example of how you would do it (from a button for example).

I added both the d3.select way and the plain JS way, both should work fine.

d3.select("#kk").on("mouseleave",function(){
  console.log("mouseleave");
});

var button = document.getElementById('trigger-event');
button.onclick = function() {
  var evt = new MouseEvent("mouseleave");
  
  // The way to dispatch the event using d3
  d3.select('#kk').node().dispatchEvent(evt);
  
  // The way to dispatch it with plain JS
  document.getElementById('kk').dispatchEvent(evt);
};
#kk {
  width:100px;
  height:100px;
  background-color:blue;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="kk">
  
</div>


<button id="trigger-event">trigger event</button>
like image 42
Hugo Migneron Avatar answered Nov 05 '22 00:11

Hugo Migneron


The following will trigger the mouseleave event on the elements via dispatchEvent().

  var event = document.createEvent('Event');
  event.initEvent('mouseleave', true, true);

  d3.selectAll("circle").node().dispatchEvent(event);

Example: http://codepen.io/anon/pen/eBYvVN (I've added a button at the bottom to trigger it. The mouseleave event is attached to the circles)

like image 4
K Scandrett Avatar answered Nov 05 '22 00:11

K Scandrett