5

I was wondering if there is a way in which its possible to integrate the manipulate package or gWidgetsManipulate package so that their outputs can be viewable/manipulable in the html/markdown output file, as I think that this would be extremely useful when developing reproducible interactive research reports. I know that googleVis has some functionality that allows it to be integrated with knitr so that the outputs go into the html file by using options like results='asis' but googleVis is currently quite restrictive in its capabilities when using sliders for example.

If the package outputs of manipulate or gWidgetsManipulate hasn't quite been integrated yet, would it be possible to suggest a workaround for the time being that will allow it to be viewed in the html file?

i.e. my current code in my Rmd file before running knitr-ing to html looks like the below...but I get the following errors.

```{r}
library(manipulate)
manipulate(plot(1:x), x = slider(5, 10))
```

with output

library(manipulate)
## Error: there is no package called 'manipulate'
manipulate(plot(1:x), x = slider(5, 10))
## Error: could not find function "manipulate"

so trying the package gWidgetsManipulate instead...

```{r}
library(gWidgetsManipulate)
manipulate(plot(1:x), x = slider(5, 10))
```

you get the error...

library("gWidgetsManipulate")
## Loading required package: gWidgets
manipulate(plot(1:x), x = slider(5, 10))
## Error: unable to find an inherited method for function ".gwindow", for signature "NULL"

I have tried to specify a guiToolkit to fix this error by using things like

options(guiToolkit="WWW")

but to no avail...

Any help would be greatly appreciated, thanks in advance

h.l.m
  • 13,015
  • 22
  • 82
  • 169
  • 2
    I guess `manipulate` is quite different with `googleVis`; the latter can write HTML/Javascript code which allows interaction, but I doubt if the former does as well. – Yihui Xie Jun 15 '12 at 05:57
  • Doesn't gWidgets or gWidgetsManipulate or any of the gWidgetsXXX packages help in writing some HTML/Javascript? – h.l.m Jun 15 '12 at 08:14
  • I do not know much about `gWidgetsManipulate`, but I'm almost sure `gWidgets` does not write HTML/JS as character strings; `gWidgetsWWW` or `gWidgetsWWW2` may create web pages, but what you really need is HTML/JS snippets which can be _embedded_ in an HTML document. – Yihui Xie Jun 15 '12 at 15:35

1 Answers1

3

If you don't absolutely need to use the gwidgets, I have a solution with Rook and googleVis that does what you want: displaying an interactive chart in html.

The script for the slider: it contains a little javascript function to display the currently chosen value. It also submits the form at each change. You can easily change the min/max/... values here.

slider_script <- '
  <input type="range" min="5" max="10" name="plot_max" value="%s" step="1" onchange="document.form1.submit(); showValue(this.value);" />
  <span id="range">%s</span>
  <script type="text/javascript">
  function showValue(newValue)
{
    document.getElementById("range").innerHTML=newValue;
  }
</script>
'

We build the code of the web page. The structure is typical for rook: html code is written inside res$write().

### this script builds the webpage
    webreport_app <- function(
      ){
      newapp = function(env) {
        req = Rook::Request$new(env)
        res = Rook::Response$new()
        # initialise variables for first execution
        if (is.null(req$POST())){
          plot_max <- 5
        } else{
          plot_max <- as.numeric(req$POST()[["plot_max"]])
        }
        res$write('<body style="font-family:Arial">')
        res$write("<H3>My App</H3>")
        res$write('<form name = "form1" method="POST">\n')
        res$write('<br> Number of dots: \n')
        res$write(sprintf(slider_script, plot_max, plot_max))
        res$write('<br><input type="submit" name="Go!">\n</form>\n')
        if (!is.null(req$POST())) {    
          # generate the plot
          library(googleVis)
          data_for_plot <- data.frame(x_var = 1:plot_max, y_var = 1:plot_max)
          Scatter1 <- gvisScatterChart(data_for_plot)
          # extract chart script
          chart_script <- capture.output(print(Scatter1, 'chart'))
          # write to html
          res$write(paste(chart_script, collapse="\n"))
          res$write("<br><br></body></html>")
        }
        res$finish()
      }
      return(newapp)
    }

And finally launch the setup and launch the html server via Rook:

library(Rook)

# launch the web app
if (exists("report_server")){
  report_server$remove(app, all = TRUE)
  report_server$stop()
  rm(report_server)
}
report_server = Rhttpd$new()
report_server$add(app = webreport_app(), name = "My_app")
report_server$start()
report_server$browse("My_app")
report_server$browse()
nassimhddd
  • 8,340
  • 1
  • 29
  • 44
  • Oh! That looks very very good so far...Thank you! Apologies if this is a basic question but running the code in the console brings up browser that is manipulable, which is great, but is it possible show exactly whats needed to be put it into an Rmd file so that when running knit2html() it integrates it into the html output e.g. i would expect the Rmd file to looks something like: `random text before r code ```{r} `code to generate the integrated rook function to view manipulable gvis object ``` `random comments after the code and integrated manipulable gvis object. – h.l.m Jul 09 '12 at 00:30
  • Also is there a way to remove the submit button so that the page updates automatically as soon as the variables are changed? Perhaps some sort of slider functionality that updates in realtime? or perhaps a 1 second refresh rate built in? – h.l.m Jul 09 '12 at 01:44
  • I would love to have a version with a static web page (that could then be generated with knitr), but the googleVis package doesn't support the google chart controls... – nassimhddd Jul 11 '12 at 08:09
  • 1
    I've edited my answer to automatically update. It's not perfect as it will update at each step... – nassimhddd Jul 11 '12 at 09:10