slidify / interactive

Interactive Documents with R
http://slidify.github.io/interactive
22 stars 61 forks source link

Interactive Console with Hint/Test Code Functionality? #2

Open mattsigal opened 11 years ago

mattsigal commented 11 years ago

I have a slide with an interactive console working. This comes with four buttons on the bottom: Run Code, Test Code, Clear Output, and Get Hint.

I am trying to get the "Get Hint" button to work, as I would like to store some code in the hint to replace in the console (to show how it can be dynamically altered).

I've tried using the same syntax as from the quiz widget:

*\ .hint This is a hint

But even that causes the slideshow to crash with the following:

Error in if (input[[paste0("runCode", i)]] != 0) return(isolate({ : argument is of length zero
Error in if (input[[paste0("runCode", i)]] != 0) return(isolate({ : argument is of length zero

Is this simply not working at the moment, or am I missing something?

Thanks!

Matt

ramnathv commented 11 years ago

First off, I am surprised that it crashes the slide deck. Do you have a link where I can see that?

If you look at the layout where the interactive console is defined, you will notice the following lines

<a class='btn  btn-small iBtn' id='getHint{{slide.num}}' rel='tooltip' 
    data-title="Get Hint" data-action='getHint'
    data-cell='{{slide.num}}' data-hint="{{slide.hint.html}}">
    <i class="icon-bookmark"></i>
</a>

The key is the placeholder {{{ slide.hint.html }}}, which suggests that you need a block named hint to populate it, as opposed to the quiz widget where you just need a class. Named widgets are required in the interactive console, so that hints are clearly distinguished from others.

Now, you can specify a named block in one of two ways

--- =hint

This is a hint

OR

--- {name: hint}

This is a hint

Let me know if this works. Also, if you can point me to a deck of yours with the error you get when you do --- .hint that would be useful too.

mattsigal commented 11 years ago

Hi Ramnath,

When I only use "hint" as a class, what happens is: 1) No errors in RStudio, until the end. 2) The background goes all black (instead of what it is set at) 3) RStudio reports:

output file: index.md
Listening on port 3292
Error in if (input[[paste0("runCode", i)]] != 0) return(isolate({ : argument is of length zero
Error in if (input[[paste0("runCode", i)]] != 0) return(isolate({ : argument is of length zero

In the browser, the slides load up to the slide with the "hint", and then stop.

This is the slide code:

--- &interactive

## Interactive Console with googleVis

```{r opts.label = 'interactive', results = 'asis'}
suppressPackageStartupMessages(library(googleVis))
Bubble <- gvisBubbleChart(Fruits, idvar="Fruit", xvar="Sales", yvar="Expenses", colorvar="Year", sizevar="Profit", options=list(hAxis='{minValue:75, maxValue:125}'))
print(Bubble, tag = 'chart')

*** .hint

M1 <- gvisMotionChart(Fruits, idvar = 'Fruit', timevar = 'Year'); print(M1, tag = 'chart')


When I change the hint like to --- {name: hint}  all the slides load properly, but I get the same error in the RStudio console, and only the title of the slide gets printed.  All the later slides load properly.

I've published the deck here: http://mattsigal.github.io/test/# and made slides 3-5 the three different hint methods.  Each results in the same - the title of the slide renders, but nothing else.

EDIT: Nevermind about the aside; just took a few minutes for the io page to update to the latest version.
ramnathv commented 11 years ago

I suspect it is because of jQuery being loaded multiple times. Here is a recommended fix.

Remove ext_widgets from your YAML front matter and don't use print or show inline. If you call the chart just as you would in your R console, slidify will automatically create a standalone html chart and embed it as an iframe. This would sandbox the js code thereby avoiding interference of the kind seen here.

Let me know of this works. I don't have my laptop right now, but can provide an example later if you are not able to get this working.

PS. Github Pages take time to update sometimes. So this is normal. Sometimes to force the update, I explicitly type index.html at the end of the link. It usually works, but YMMV.

mattsigal commented 11 years ago

I've removed the ext_widgets from the YAML (I realize now that I'll be hosting any rCharts examples externally anyways so it doesn't actually affect anything), and replaced each of the "print(Bubble, tag = 'chart')" lines with plot(Bubble) as I would in the console.

Unfortunately, same issue - the plots don't render, and the console gives the same error.

While I have your attention, could you also see what I'm doing wrong here? I've put together a shiny app to show your nvd3 example, and the UI appears but no plot. I'm sure I'm missing something simple, but I can't seem to figure out what.

# ui.R
library(shiny)
library(rCharts)

shinyUI(pageWithSidebar(
  headerPanel("rCharts: Interactive Charts from R using NVD3.js"),

  sidebarPanel(
    selectInput('sex', 'Choose Sex', c('Male', 'Female')),
    selectInput('type', 'Choose Type', c('multiBarChart', 'multiBarHorizontalChart'))
  ),

  mainPanel(
    tags$div(id = 'nvd3plot', class='shiny-html-output nvd3 rChart')
  )
))

## server.r
library(shiny)
library(rCharts)

shinyServer(function(input, output) {

  output$nvd3plot <- renderChart({
    haireye = as.data.frame(HairEyeColor)
    n1 <- nPlot(Freq ~ Hair, group = 'Eye', type = input$type,
                data = subset(haireye, Sex == input$sex)
    )
    n1$set(dom = 'nvd3plot', width = 600)
    n1
  })  
})

This doesn't work locally or via glimmer.

ramnathv commented 11 years ago

Okay. Let me create a minimal example to show you how to do both.

I am teaching all day, so will be able to get around to this only later in the day.

mattsigal commented 11 years ago

Thanks! I would really appreciate it. The "hints" thing isn't really high priority (would just be very convenient for the presentation; but I could always just used the clipboard for the same purpose); but I would like to know what I'm doing wrong in the shiny app.

mattsigal commented 11 years ago

One other issue that has arisen: I am including an rChart in my presentation that doesn't require shiny (and so can be included in my markdown file, rather than in an iframe). The plot loads perfectly (http://mattsigal.github.io/test/#44), however, it seems in the rendering, it loses the parameter customizations I did.

```{r results='asis', echo=FALSE, fig.align='center', cache=FALSE}
df <- as.data.frame(matrix(c(18, 3, 1, 1, 84, 4, 7, 3, 87, 12, 9, 7),ncol=4,nrow=3,byrow=TRUE)) 
colnames(df) <-c("Non-Smoker", "Occasional Smoker", "Regular Smoker", "Heavy Smoker")
rownames(df) <-  c("None", "Some", "Freq")

a <- rCharts:::Highcharts$new()
a$params$width <- 900
a$params$heigh <- 700
a$chart(type = "column")
a$title(text = "Smoking and Exercise")
a$yAxis(title = "Count")
a$plotOptions(column = list(stacking = "normal"))
a$xAxis(title ="Category", categories = c("No Exercising", "Some Exercising", "Frequent Exercising"))
a$data(df);
a$print('hchart1', include_assets = TRUE, cdn = FALSE)


When I render this locally, the width and height arguments get properly applied (making the chart bigger), and the yAxis title appears.  However, when I publish this to github, these seem to get disregarded?  Any idea why?

EDIT: Wow, github io likes to make me feel silly.  I reloaded the slide and now the width and height arguments appear to have been retained, but there still is no title on the y-Axis.
EDIT2: It seems that it actually wants to make me crazy - some loads it is the width I specified; others it reverts back to the small size.  I can't seem to pinpoint why.
mattsigal commented 11 years ago

Last question, I swear! I'm still tinkering with trying to get an interactive console hosted on glimmer. So far, I've authored a new slidify deck on Glimmer with the following code:

---
title       : Interactive Console with rCharts
author      : Matthew Sigal
job         : 
framework   : io2012        # {io2012, html5slides, shower, dzslides, ...}
highlighter : highlight.js  # {highlight.js, prettify, highlight}
hitheme     : tomorrow      # 
widgets     : [bootstrap, quiz, shiny, interactive]
mode        : selfcontained # {standalone, draft}

--- &interactive
## Interactive Console

```{r opts.label = 'interactive', results = 'asis'}
require(rCharts)
a <- Highcharts$new()
a$chart(type = "spline")
a$series(data = c(1, 3, 2, 4, 5, 4, 6, 2, 3, 5, NA), dashStyle = "longdash")
a$series(data = c(NA, 4, 1, 3, 4, 2, 9, 1, 2, 3, 4), dashStyle = "shortdot")
a$legend(symbolWidth = 80)
a$print('chart3')


I've also placed the Highchart files into the widgets directory.  The html loads (http://glimmer.rstudio.com:8787/files/ShinyApps/rChart/rChart/index.html#1), but it can't find the Highcharts object (and I'm now sure it is not loading rCharts properly).

In summary, 4 issues:
1) The use of "hints" in an interactive console environment (low priority).
2) The proper way of calling an nPlot within a Shiny application.
3) The passing of parameters into an rCharts object (and their maintenance after publishing the slidify presentation)
4) How to incorporate rCharts (specifically how to access the Highcharts generator) from a glimmer environment.

Sorry for the deluge!  This is my first serious foray into this area.  I truly appreciate your help!
ramnathv commented 11 years ago

Will reply in detail later.

But DON'T put interactive console on glimmer. There are security issues with allowing anyone to run arbitrary R code on the server. OpenCPU is more secure which is why the online fallback makes use of it.

mattsigal commented 11 years ago

Good to know :+1: I've taken it down. I'm looking forward to your response!

ramnathv commented 11 years ago

Matt, I am not sure how I did not notice this earlier, but you are using an older version of Slidify. You will need to upgrade to the dev branch using

pkgs <- c('slidify', 'slidifyLibraries', 'rCharts')
devtools::install_github(pkgs, "ramnathv", ref = "dev")

The best way to proceed after upgrading is to make a copy of your slides folder, and delete libraries. This is essential because I changed a few things in the dev version which make it backword incompatible. After you delete libraries you can run slidify or runDeck and I think all problems will be resolved.

Let me know if you need any clarifications, or are not able to get it to work.

mattsigal commented 11 years ago

Hi Ramnath,

I'm actually on the latest dev version of each package, from sessionInfo():

other attached packages:
[1] rCharts_0.3.53         shiny_0.7.0.99         slidifyLibraries_0.3.1 slidify_0.3.52 

I was tinkering a lot with the presentation yesterday, and do have most things running as I would like them to (latest draft: http://mattsigal.github.io/test/).

However, I still haven't been able to get "hints" to work with the interactive console (slide 35) - as a workaround, I just put the text I wanted in my hint above the console and colored it white so I can copy/paste it in during the presentation on the fly.

As another case of weirdness, on that same slide, it seems like the R code is being sent as HTML instead of plain text (even though the chunk specifies results = "asis"). For example, if I put a line break, it shows up in the console as

(and the tab characters from RStudio are being rendered in the window too). Bizarre?

Otherwise, I figured out what I was doing wrong with nPlot (was simply calling it incorrectly, because I was basing my template on the rPlot example). So, no problems there. Thanks again for your help!

ramnathv commented 11 years ago

Okay. On Slide 35, I don't see any HTML in the googleVis code. Am I missing something here?

I will experiment with the hints part and send you a minimal example today.

mattsigal commented 11 years ago

RE: Slide 35, it is because in the current draft I removed the line breaks. I've published a new version to show you what I mean: http://mattsigal.github.io/test2/index.html#35

In the console, it now renders as: suppressPackageStartupMessages(library(googleVis))

<p>bub <- gvisBubbleChart(Fruits, 
          idvar="Fruit", xvar="Sales",
          yvar="Expenses", colorvar="Year", 
          sizevar="Profit", options=list(hAxis='{minValue:75, maxValue:125}')
        )</p>

<p>print(bub, tag = 'chart')

If I remove all the line breaks, then the tags don't show up in the console. The chunk has the following options: ```{r bubble, opts.label = 'interactive', results = 'asis'}

Also, this is probably a simple question but: I have one plot hosted on Rpubs and as a gist. If I embed the Rplot, I get the toolbars visible upon loading the slide; the gist loads the rCharts template which is also fairly busy. Is there anyway to just embed the plot itself in my iframe?

ramnathv commented 11 years ago

You can directly embed your chart from the following link

http://rstudio-pubs-static.s3.amazonaws.com/9773_b39e1a7b7b3b44159f99ba358c0925b7.html

The trick is to look at the page source in chrome and pull out the actual page which rpubs embeds as an iframe.

The reason why you see those <p> tags is because your code is heavily indented and as a result markdown is processing it to HTML. A quick workaround is to enclose the interactive code chunks within <div> and </div> tags. The idea is that anything within div tags is not going to be touched by markdown.

I know this is a matter of style, but I would write your code as below. It would avoid the problem you run into and reduce extraneous whitespace.

bub <- gvisBubbleChart(Fruits, 
  idvar = "Fruit", 
  xvar = "Sales", 
  yvar = "Expenses", 
  colorvar = "Year", 
  sizevar = "Profit", options=list(hAxis='{minValue:75, maxValue:125}')
)
mattsigal commented 11 years ago

Yup, wrapping the console chunk in div tags did the trick! Awesome. So, I guess all that remains is adding hints to the interactive console (the original query, haha)