18 Introduction

The same plotly.js events that we accessed in shiny through event_data() in section 17.2 can also be leveraged purely client-side with some custom JavaScript (JS). That means, by knowing a little bit about JS and the plotly.js library, we can extend graphs created with the R package to have custom behavior without requiring a client-server application. This portion of the book focuses on writing custom responses to commonly used plotly.js events, but a lot of the same tools and techniques could be used to extend these graphs in other ways as well.

To add a custom JS event handler to a plotly graph, you can leverage the onRender() function from the htmlwidgets package. This R function accepts a JS function as a string and calls that function when the widget is done rendering in the browser. The JS function needs (at least) one argument, el, which is the Document Object Model (DOM) element containing the plotly graph. Figure 18.1 shows how you could use onRender() to log (and inspect) the DOM element to your browser’s JS console. You can open the console of any browser (including RStudio!) with right-click -> “Inspect Element” -> “Console” tab (or similar). To demonstrate some useful DOM element’s properties, Figure 18.1 uses Firefox to inspect the element as a global variable, but as Figure 20.1 shows, Chrome currently offers better tools for code debugging the JS function provided to onRender() (e.g., setting breakpoints in virtual memory).

plot_ly(z = ~volcano) %>%
  onRender("function(el) { console.log(el); }")

FIGURE 18.1: Using htmlwidgets::onRender() to inspect the relevant DOM instance containing the plotly graph and information related to it’s current display. The _fullData and _fullLayout attributes bound to the element are ‘internal’ (meaning relying on this information in production code is discouraged), but do provide a useful description of the chart’s current state, especially if you need access to computations done by plotly.js (e.g., axis tick placement).

If you’re completely new to JavaScript and JSON, section 19 provides a foundation for understanding the subsequent sections, but those already familiar can skip ahead to section 20.