repr
repr copied to clipboard
ggvis
First, thanks for working on this, its really nice. I notice that ggvis output is not displayed, e.g.,
library(ggvis)
mtcars %>% ggvis(~mpg, ~wt) %>% layer_points()
doesn't produce anything. Any chance this can be supported?
Depending what you want, it's as easy as finding out what knit_print.ggvis(...) produces (https://github.com/rstudio/ggvis/blob/master/R/print.R#L113) and then porting that function over to a repr_<type>.ggvis.
Great, I'll look into it.
I took a look but it wasn't really clear to me how to proceed. Even "static" ggvis display needs a bunch of javascript, and converting to png or svg requires nodejs modules. I may try again later but I'm giving up for now.
We can display HTML and JS easily enough. For now, JS libraries either have to be sent with the data every time or loaded from a CDN, but we're thinking about ways to send JS libraries from the kernel to the browser.
Can the notebook only output javascript libs once? e.g. displaying many ggvis plots will output the main plot html for each plot, but include the javascript only once?
That's what we're working on having a good way to do. At the moment, some libraries will ask the user to manually run something like notebook_init() to set up the JS libraries.
knitr has that actually worked out in the 'knit_asis' objects: printed objects can add metadata (with each printed object) and knitr collects them and only displays each object once. The metadata objects have a class of "html_depencies", so they can be icked out easily.
Translated into the notebook: the kernel would send the js/css dependencies in the metadata list and the notebook (or knitpy :-)) would take a display_data and if it displays html, it would also look for 'html_depencies' in the metadata and would display that too...
Here is such a object for a ggvis object:
> y = knit_print.ggvis(x)
> y
[1] "<!--html_preserve--><div id=\"plot_id408708061-container\" class=\"ggvis-output-container\">\n<div id=\"plot_id408708061\" class=\"ggvis-output\"></div>\n<div class=\"plot-gear-icon\">\n<nav class=\"ggvis-control\">\n<a class=\"ggvis-dropdown-toggle\" title=\"Controls\" onclick=\"return false;\"></a>\n<ul class=\"ggvis-dropdown\">\n<li>\nRenderer: \n<a id=\"plot_id408708061_renderer_svg\" class=\"ggvis-renderer-button\" onclick=\"return false;\" data-plot-id=\"plot_id408708061\" data-renderer=\"svg\">SVG</a>\n | \n<a id=\"plot_id408708061_renderer_canvas\" class=\"ggvis-renderer-button\" onclick=\"return false;\" data-plot-id=\"plot_id408708061\" data-renderer=\"canvas\">Canvas</a>\n</li>\n<li>\n<a id=\"plot_id408708061_download\" class=\"ggvis-download\" data-plot-id=\"plot_id408708061\">Download</a>\n</li>\n</ul>\n</nav>\n</div>\n</div>\n<script type=\"text/javascript\">\nvar plot_id408708061_spec = {\n \"data\": [\n {\n \"name\": \".0\",\n \"format\": {\n \"type\": \"csv\",\n \"parse\": {\n \"mpg\": \"number\",\n \"wt\": \"number\"\n }\n },\n \"values\": \"\\\"mpg\\\",\\\"wt\\\"\\n21,2.62\\n21,2.875\\n22.8,2.32\\n21.4,3.215\\n18.7,3.44\\n18.1,3.46\\n14.3,3.57\\n24.4,3.19\\n22.8,3.15\\n19.2,3.44\\n17.8,3.44\\n16.4,4.07\\n17.3,3.73\\n15.2,3.78\\n10.4,5.25\\n10.4,5.424\\n14.7,5.345\\n32.4,2.2\\n30.4,1.615\\n33.9,1.835\\n21.5,2.465\\n15.5,3.52\\n15.2,3.435\\n13.3,3.84\\n19.2,3.845\\n27.3,1.935\\n26,2.14\\n30.4,1.513\\n15.8,3.17\\n19.7,2.77\\n15,3.57\\n21.4,2.78\"\n },\n {\n \"name\": \"scale/x\",\n \"format\": {\n \"type\": \"csv\",\n \"parse\": {\n \"domain\": \"number\"\n }\n },\n \"values\": \"\\\"domain\\\"\\n9.225\\n35.075\"\n },\n {\n \"name\": \"scale/y\",\n \"format\": {\n \"type\": \"csv\",\n \"parse\": {\n \"domain\": \"number\"\n }\n },\n \"values\": \"\\\"domain\\\"\\n1.31745\\n5.61955\"\n }\n ],\n \"scales\": [\n {\n \"name\": \"x\",\n \"domain\": {\n \"data\": \"scale/x\",\n \"field\": \"data.domain\"\n },\n \"zero\": false,\n \"nice\": false,\n \"clamp\": false,\n \"range\": \"width\"\n },\n {\n \"name\": \"y\",\n \"domain\": {\n \"data\": \"scale/y\",\n \"field\": \"data.domain\"\n },\n \"zero\": false,\n \"nice\": false,\n \"clamp\": false,\n \"range\": \"height\"\n }\n ],\n \"marks\": [\n {\n \"type\": \"symbol\",\n \"properties\": {\n \"update\": {\n \"fill\": {\n \"value\": \"#000000\"\n },\n \"size\": {\n \"value\": 50\n },\n \"x\": {\n \"scale\": \"x\",\n \"field\": \"data.mpg\"\n },\n \"y\": {\n \"scale\": \"y\",\n \"field\": \"data.wt\"\n }\n },\n \"ggvis\": {\n \"data\": {\n \"value\": \".0\"\n }\n }\n },\n \"from\": {\n \"data\": \".0\"\n }\n }\n ],\n \"width\": null,\n \"height\": null,\n \"legends\": [],\n \"axes\": [\n {\n \"type\": \"x\",\n \"scale\": \"x\",\n \"orient\": \"bottom\",\n \"layer\": \"back\",\n \"grid\": true,\n \"title\": \"mpg\"\n },\n {\n \"type\": \"y\",\n \"scale\": \"y\",\n \"orient\": \"left\",\n \"layer\": \"back\",\n \"grid\": true,\n \"title\": \"wt\"\n }\n ],\n \"padding\": null,\n \"ggvis_opts\": {\n \"keep_aspect\": false,\n \"resizable\": true,\n \"padding\": {},\n \"duration\": 250,\n \"renderer\": \"svg\",\n \"hover_duration\": 0,\n \"width\": null,\n \"height\": null\n },\n \"handlers\": null\n};\nggvis.getPlot(\"plot_id408708061\").parseSpec(plot_id408708061_spec);\n</script><!--/html_preserve-->"
attr(,"class")
[1] "knit_asis"
attr(,"knit_meta")
attr(,"knit_meta")[[1]]
$name
[1] "jquery"
$version
[1] "1.11.0"
$src
$src$file
[1] "C:/portabel/Rlibs/ggvis/www/lib/jquery"
$meta
NULL
$script
[1] "jquery.min.js"
$stylesheet
NULL
$head
NULL
$attachment
NULL
attr(,"class")
[1] "html_dependency"
[...]
attr(,"knit_meta")[[5]]
$name
[1] "lodash"
$version
[1] "2.2.1"
$src
$src$file
[1] "C:/portabel/Rlibs/ggvis/www/lib/lodash"
$meta
NULL
$script
[1] "lodash.min.js"
$stylesheet
NULL
$head
[1] "<script>var lodash = _.noConflict();</script>"
$attachment
NULL
attr(,"class")
[1] "html_dependency"
[...]
attr(,"knit_cacheable")
[1] FALSE
knit_print and the asis output is almost like the the messaging spec: it misses the mimetype but has better dependencies handling for js/css. See here in action: http://ggvis.rstudio.com/0.1/quick-examples.html
whoops, didn’t mean to do that
well, all of this can be hackishly circumvented.
define a function preload that tests some condition (e.g. existence of a global variable), and if it doesn’t exist, loads some script:
preload(window.jQuery, '/path/to/jquery.min.js', function() {
actual_code()
})
or, the proper way: allow metadata on where to find JS modules and simply import/require them:
import jQuery from 'jquery'
// or
const jQuery = require('jquery')
This should probably be implemented in ggvis, like I just did for googleVis in https://github.com/mages/googleVis/pull/39