7 Interactivity

Read: IDVW2, Chapter 10 Interactivity

7.1 Lecture slides

interactivity.pdf

7.2 Binding event listeners

(100, 150)

Open Developer Tools and try this code in the Console:

d3.select("svg")
  .on("click", function () {
    d3.select("svg")
      .append("text")
        .attr("x", "100")
        .attr("y", "40")
        .text("Hello World");
        });

7.3 What is this?

In the context of event handlers, “this” is the element that received the event, a.k.a. what you clicked on if it’s a click event.

Examples from the first chapter:

d3.select("line")
  .on("click", function() {
    d3.select(this)
      .attr("stroke-width", "10");
      });

v6

d3.select("svg")
  .on("click", function(event) {
    d3.select("text")
      .text(`(${d3.pointer(event).map(Math.round)})`)
      });

v5

d3.select("svg")
  .on("click", function() {
    d3.select("text")
      .text(`(${d3.mouse(this).map(Math.round)})`)
      });

We can separate the function and the event listener:

function goyellow() {
  d3.select(this)
    .attr("fill", "yellow")
    };
d3.select("circle")
  .on("mouseover", goyellow);

Try this in the Console:

v6

d3.select("svg")
  .on("click", function (event) {
    console.log(d3.pointer(event).map(Math.round));
    });

v5

// won't work on this page
d3.select("svg")
  .on("click", function () {
    console.log(d3.mouse(this));
    });

7.3.1 Location on SVG

v6 d3.pointer(event)

v5 d3.mouse(this)

7.3.2 Attribute of an element

d3.select(this).attr("id");

7.3.3 Value of radio button

d3.select(this).node().value; (string)

+d3.select(this).node().value; (number)

7.4 Add / remove “buttons”

(HTML paragraphs are used as buttons in this example.)

HTML:

<p id="add">Add an element</p>
<p id="remove_left">Remove bar (left)</p>
<p id="remove_right">Remove bar (right)</p>

JavaScript:

d3.selectAll("p")
    .on("click", function () {
      var paraID = d3.select(this).attr("id");
      if (paraID == "add") {
          var newvalue = Math.floor(Math.random()*400);
          bardata.push(newvalue);
          } else if (paraID == "remove_left") {
          bardata.shift();
          } else {
          bardata.pop();
          };
      update(bardata);
      });

7.5 Putting it all together

Vertical bar chart with add / remove buttons and general update pattern

vertical_bar.html

7.6 Dependent event listeners

In these examples, the behavior or existence of one event listener depends on another.

7.6.1 Global variable example

Here the circle click behavior depends on the value of the radio button: if the “Move left” radio button is checked, the circle will move left when clicked. If the “Move right” radio button is checked, the circle will move right when clicked.

A global variable is used to keep track of the radio button value. The event listener on the circle conditions the behavior on the value of this global variable.

Click the circle.

 Move left  Move right
svg#radio

// global variable keeps track of which radio button is clicked
var action = "left";
d3.select("div#rad")
  .selectAll("input")
  .on("click", function() { action = d3.select(this).node().value; });
      
// circle click behavior depends on value of "action"
d3.select("svg#radio").select("circle")
  .on("click", function () {
    if (action == "left") {
      var cx_new = +d3.select(this).attr("cx") - 50;
      if (cx_new < 20) cx_new = 20;
      } else {
      var cx_new = +d3.select(this).attr("cx") + 50;
      if (cx_new > 280) cx_new = 280;
      }
    d3.select(this)
      .transition()
      .duration(500)
      .attr("cx", cx_new);
      });

7.6.2 Turn off event listener

In this example, the event listeners on the squares are turned on or off depending on the value of the radio button. Event listeners can be removed by setting the behavior to null.

Click a square.

 Red active  Blue active

svg#radio2
// movement function
var jump = function () {
      d3.select(this).transition().duration(500)
      .attr('y', '0')
      .transition().duration(500).ease(d3.easeBounce)
      .attr('y', '75');
};

// initial setup: add event listener to red square
d3.select("svg#radio2")
  .select("rect#red")
  .on("click", jump);
    
// switch event listeners if radio button is clicked
d3.select("div#rad2").selectAll("input")
  .on("click", function () {
  if (d3.select(this).node().value == "blue") {
    d3.select("svg#radio2").select("rect#blue").on("click", jump);
    d3.select("svg#radio2").select("rect#red").on("click", null);
    } else {
    d3.select("svg#radio2").select("rect#red").on("click", jump);
    d3.select("svg#radio2").select("rect#blue").on("click", null);
    }
});