ramnathv / slidify

Generate reproducible html5 slides from R markdown
http://www.slidify.org
844 stars 339 forks source link

Shiny does not always render in Slidify #230

Closed mege closed 11 years ago

mege commented 11 years ago

Why do Slidify pages with Shiny iframes not render without refreshing the browser?

When viewing a Slidify page with a Shiny element embedded with an

Directly loading the URL http://glimmer.rstudio.com/wisconsindpi/correlation/ in the browser will render fine.

Thanks.

ramnathv commented 11 years ago

Page 5 renders fully for me without a page refresh. However, I have encountered this issue before. When I inspected what was happening using Chrome's Developer tools, I saw that for some reason, the websocket connection was listed pending, and needed a refresh. I suspect it might be a timeout issue.

The trouble is that there is little you can do to control an external iframe. It should really work like an external page. But with websockets, I imagine something different happens.

I will leave this issue open, should a better solution crop up.

mege commented 11 years ago

The problem does seem to be interment. I share your hunch that there is a timeout problem. It looks like slidify loads the l external resources for all pages when when the first page viewed, correct?

When a slidify page becomes active is there a way to check that all resources have been loaded and take action if there is an error or loading did not complete?

One thought, would it be possible to ad a UI control to slidify that would allow the user to refresh the active slide?

Thanks for creating Slidify.

ramnathv commented 11 years ago

You are right that Slidify loads all resources on page load. Now that you mention it, I remember an approach I created for loading an iframe after a slide is loaded for a d3js visualization. Here is a wiki post explaining the idea.

I think you could use this approach to dynamically load the iframe only when the particular slide is reached. This should sort out the timeout issue (if it is the issue)

If this works, would you still need the UI control to refresh active slide? If yes, can you provide a use case. I would be happy to implement something if there is a solid use case for it. If not, I can definitely point you to a way you can add such controls yourself by tweaking the slide layout.

mege commented 11 years ago

The refresh may be helpful but first lets see if on-demand-loading fixes the problem. When I tried the code mentioned in the wiki post I'm getting a null slide. Has something changed in Slidify?

This seems like it should work but I'm just getting a blank slide:

---
title       : My Title
subtitle    : Something Smart here
author      : 
job         : 
framework   : io2012        # {io2012, html5slides, shower, dzslides, ...}
highlighter : highlight.js  # {highlight.js, prettify, highlight}
hitheme     : tomorrow      # 
widgets     : []            # {mathjax, quiz, bootstrap}
mode        : selfcontained # {standalone, draft}

--- #myslide

<script>
$('#myslide').on('slideenter', function(){
  $(this).find('article')
    .append('<iframe src="http://bl.ocks.org/mbostock/raw/1256572/"></iframe>')
});
$('#myslide').on('slideleave', function(){
  $(this).find('iframe').remove();
});

ramnathv commented 11 years ago

Are you use the master or the dev version of Slidify? Can you post the html file that you get as a result of slidifying this slide?

mege commented 11 years ago

We are using slidify’ version 0.3.3.

Here is the .html that is generated

<!DOCTYPE html>
<html>
<head>
  <title>My Title</title>
  <meta charset="utf-8">
  <meta name="description" content="My Title">
  <meta name="author" content="">
  <meta name="generator" content="slidify" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta http-equiv="X-UA-Compatible" content="chrome=1">
  <link rel="stylesheet" href="libraries/frameworks/io2012/css/default.css" media="all" >
  <link rel="stylesheet" href="libraries/frameworks/io2012/phone.css" 
    media="only screen and (max-device-width: 480px)" >
  <link rel="stylesheet" href="libraries/frameworks/io2012/css/slidify.css" >
  <link rel="stylesheet" href="libraries/highlighters/highlight.js/css/tomorrow.css" />
  <base target="_blank"> <!-- This amazingness opens all links in a new tab. -->
  <script data-main="libraries/frameworks/io2012/js/slides" 
    src="libraries/frameworks/io2012/js/require-1.0.8.min.js">
  </script>

    <link rel="stylesheet" href = "assets/css/ribbons.css">

</head>
<body style="opacity: 0">
  <slides class="layout-widescreen">

    <!-- LOGO SLIDE -->
    <!-- END LOGO SLIDE -->

    <!-- TITLE SLIDE -->
    <!-- Should I move this to a Local Layout File? -->
    <slide class="title-slide segue nobackground">
      <hgroup class="auto-fadein">
        <h1>My Title</h1>
        <h2>Something Smart here</h2>
        <p><br/></p>
      </hgroup>
          </slide>

    <!-- SLIDES -->
      <slide class="" id="myslide" style="background:;">
  <hgroup>

  </hgroup>
  <article>
    <script>
$('#myslide').on('slideenter', function(){
  $(this).find('article')
    .append('<iframe src="http://bl.ocks.org/mbostock/raw/1256572/"></iframe>')
});
$('#myslide').on('slideleave', function(){
  $(this).find('iframe').remove();
});
</script>

  </article>
  <!-- Presenter Notes -->
</slide>

    <slide class="backdrop"></slide>
  </slides>

  <!--[if IE]>
    <script 
      src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js">  
    </script>
    <script>CFInstall.check({mode: 'overlay'});</script>
  <![endif]-->
</body>
<!-- Grab CDN jQuery, fall back to local if offline -->
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js"></script>
<script>window.jQuery || document.write('<script src="libraries/widgets/quiz/js/jquery-1.7.min.js"><\/script>')</script>
<!-- Load Javascripts for Widgets -->
<!-- LOAD HIGHLIGHTER JS FILES -->
<script src="libraries/highlighters/highlight.js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<!-- DONE LOADING HIGHLIGHTER JS FILES -->
</html>
ramnathv commented 11 years ago

Okay. I get why it is not working. The trouble is that your script requires jQuery which is being loaded at the end of the file. There are two ways to fix this.

One, you can either upgrade to the dev version of Slidify on github (in which case you have to upgrade slidifyLibraries also to the dev version).

Alternately, you can manually insert jQuery at the top of your document, so that the script works.

mege commented 11 years ago

I spent some time looking around slidify.org but was not able to find how to upgrade to the dev version of Slidify. We are using:

library(devtools)
install_github('slidify', 'ramnathv')
install_github('slidifyLibraries', 'ramnathv')

What do I need to do differently?

Thanks.

ramnathv commented 11 years ago

Oh sorry. Here is how you would do it. Essentially, you will tell install_github, the branch from which to install, which in this case is dev. Otherwise it defaults to master.

library(devtools)
install_github('slidify', 'ramnathv', ref = 'dev')
install_github('slidifyLibraries', 'ramnathv', ref = 'dev')
mege commented 11 years ago

Sorry this is turning into a long running thread, but the dev version is throwing an error.
Any thoughts?

> slidify('test.Rmd')

processing file: test.Rmd
  |.................................................................| 100%
  ordinary text without R code

output file: test.md

Error in render(value, context) : could not find function "tmpl"
In addition: Warning message:
In partial(key$key[i], partials, indent) :
  No partial 'head' or file 'head.mustache' found

Here is the simple case: test.Rmd

---
title       : My Title
subtitle    : Something Smart here
author      : 
job         : 
framework   : io2012        # {io2012, html5slides, shower, dzslides, ...}
highlighter : highlight.js  # {highlight.js, prettify, highlight}
hitheme     : tomorrow      # 
widgets     : []            # {mathjax, quiz, bootstrap}
mode        : selfcontained # {standalone, draft}

--- #myslide

<script>
$('#myslide').on('slideenter', function(){
  $(this).find('article')
    .append('<iframe src="http://bl.ocks.org/mbostock/raw/1256572/"></iframe>')
});
$('#myslide').on('slideleave', function(){
 $(this).find('iframe').remove();

});

ramnathv commented 11 years ago

Delete the libraries folder before you slidify. The trouble is that the dev versions uses a slightly different folder structure, and by design slidify does not overwrite existing directories.

mege commented 11 years ago

The javascript .on('slideenter'....) works for us. Thanks a bunch for the help.

Is the change in going to the dev version from the default color scheme on the titleslide from a pleasant grey to a unappetizing green a bug?

ramnathv commented 11 years ago

Oh, let me fix that. I use the green in my presentations, and I must have forgotten to remove custom css when I pushed to Github.

ramnathv commented 11 years ago

For now, you can add some custom CSS to your deck (any css file in assets/css automatically gets linked). These are the lines which control the background and the font colors on the title slide.

.title-slide {
  background-color: #CBE7A5; /* #EDE0CF; ; #CA9F9D*/
}

.title-slide hgroup > h1{
 font-family: 'Oswald', 'Helvetica', sanserif; 
}

.title-slide hgroup > h1, 
.title-slide hgroup > h2 {
  color: #535E43 ;  /* ; #EF5150*/
}
mege commented 11 years ago

Sorry to be such a noob.

I added the code you specified to the file assets/css/myStyle.css but nothing changed. What am I missing?

ramnathv commented 11 years ago

Oh, did you change the background color and the font colors? If you did not change them from what I pasted here, then you won't see any change :)