6.3 Designing an htmlwidget interface

The plotly.js library, as with many other JavaScript graphing libraries, strives to describe any plot through a plot specification defined via JavaScript Object Notation (JSON). JSON is a language independent data-interchange format that was originally designed for JavaScript, but parsers for many different languages now exist, including R (Temple Lang 2014); (Ooms 2014). JSON is a recursive key-value data structure (similar to a list in R), and essentially any valid JavaScript value has a natural R equivalent (e.g., NULL/null). As a result, any JSON object can be created from an appropriate R list, meaning that theoretically any plotly.js plot can be described via an R list. However, simply providing a bridge between R lists and JSON does not guarantee a powerful or usable interface, especially for a general purpose graphing library.

Although it can be complicated to implement, R interfaces to JavaScript graphing libraries should leverage R’s strong resources for computing on the language to design a more expressive interface (Wickham 2014). It should also look and feel like (and work well with!) other commonly used interfaces in R. A good way to do this is to embrace (pure and predictable) functional programming. Most importantly, this implies that every function modifies a central type of object – meaning that every function input and output the same type of object (predictable). Furthermore, if the output of a function can be determined completely by the input (i.e., pure), it removes any need to search for other code that may be affecting the output. In the case of providing an interface to a JavaScript graphing library, there are a number of reasons why the central object should inherit from the central object provided by the htmlwidgets package.

The idea of interfacing R with JavaScript libraries via JSON data transfer has been popular approach for quite some time (Vaidyanathan 2013); (Hocking, VanderPlas, and Sievert 2015); (Sievert and Shirley 2014). The R package htmlwidgets standardized this bridge, and provides some additional infrastructure for making sure the HTML output works as expected in multiple contexts (in the R console or RStudio, within rmarkdown documents, and even embedded inside shiny apps). The htmlwidgets package itself is opinionated about the data structure used to represent the widget in R since it needs to retain meta-information about the widget, such as the sizing policy. To avoid surprise, widget authors should strive to have all functions in their interface modify this data structure.21

JavaScript graphing libraries usually have strong requirements about the JSON structure used to create a plot. In some cases, the R interface needs to know about these requirements in order to faithfully translate R objects to JSON. For example, in plotly.js some attributes must always be an array (e.g. x/y), even if they are length 1, while other attributes cannot be an array must be a literal constant (e.g. name). This leads to a situation where the translation rules from R to JSON cannot be simply “box all vectors of length 1 into an array (or not)”:

list(x = 1, y = 1, name = "A point") => {x: [1], y: [1], name: "A point"}

Thankfully plotly.js provides a plot schema which declares types for each attribute that plotly leverages internally. If necessary, plotly tries to coerce each attribute to its expected type at print time, and also searches for any unsupported attributes that may have been specified by the user (and throws a warning that the attribute will be ignored). This helps

References

Temple Lang, Duncan. 2014. RJSONIO: Serialize R Objects to Json, Javascript Object Notation. http://CRAN.R-project.org/package=RJSONIO.

Ooms, Jeroen. 2014. “The Jsonlite Package: A Practical and Consistent Mapping Between Json Data and R Objects.” arXiv:1403.2805 [stat.CO]. http://arxiv.org/abs/1403.2805.

Wickham, Hadley. 2014. Advanced R. Chapman & Hall.

Vaidyanathan, Ramnath. 2013. RCharts: Interactive Charts Using Javascript Visualization Libraries. https://github.com/ramnathv/rCharts/.

Hocking, Toby Dylan, Susan VanderPlas, and Carson Sievert. 2015. Animint: Interactive Animations.

Sievert, Carson, and Kenneth E Shirley. 2014. “LDAvis: A method for visualizing and interpreting topics.” Proceedings of the Workshop on Interactive Language Learning, Visualization, and Interfaces, June, 1–8. http://nlp.stanford.edu/events/illvi2014/papers/sievert-illvi2014.pdf.


  1. The plotly package initially fought this advice and represented plotly objects using a special data frame with a special print method to enable the data-plot-pipeline. I have since changed my mind and decided special methods for popular generic functions should be provided instead.