Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iframe support #252

Closed
bhaskarvk opened this issue Dec 13, 2016 · 4 comments
Closed

iframe support #252

bhaskarvk opened this issue Dec 13, 2016 · 4 comments

Comments

@bhaskarvk
Copy link

I know there are already quite a bit of issues/PRs that talk about iframe support.
This is not an issue per se, but request for comment on my new package https://github.com/bhaskarvk/widgetframe.

It allows embedding widgets inside responsive iframes using [PymJS}(http://blog.apps.npr.org/pym.js/).

It's still work in progress and the I'm almost certain the shiny part is not currently working (Not even sure why one would want a widget rendered in an iframe in a shiny env). But it works for embedding widgets inside R markdown / bookdown / CMS / static sites.

You can read the package documentation at https://bhaskarvk.github.io/widgetframe/.

I didn't use srcdoc coz I feel keeping the widget code in a separate HTML has certain advantages.
My primary use cases were
a) Being able to produce a widget HTML which can be embedded in a responsive iframe of a CMS (blogger/wordpress) or a static HTML site that is built outside of R.
b) Being able to knit widgets in R Markdown sites and bookdown such that their CSS properties are not overridden by the site's global CSS properties.

If possible I would like some input/comments on my package. cc @jcheng5 @timelyportfolio.

@ramnathv
Copy link
Owner

This looks great @bhaskarvk. One key question is what happens when you use it in Rmarkdown's standalone mode. How do the assets of the iframe get handled. Does pandoc inline those as well?

@bhaskarvk
Copy link
Author

bhaskarvk commented Dec 13, 2016

So here are a few scenarios and how it works.

library(leaflet)
library(widgetframe)
l <- leaflet() %>% addTiles()

Scenario 1

htmltools::saveWidget(frameableWidget(l),'leaflet.html')

This will result in a leaflet.html (either self-contained or not depending on 'selfcontained' option passed to saveWidget). frameableWidget doesn't create a new widget, it merely adds PymJS html Dependency and the PymJS child initialization code to the widget. The resulting leaflet.html can be easily embedded in a CMS/static HTML site provided that site has the Parent PymJS init code. It can also work w/o the Parent PymJS init code inside a regular iFrame but you lose the responsiveness that PymJS provides.

Code: https://github.com/bhaskarvk/widgetframe/blob/master/R/widgetframe.R#L57

Scenario 2

w <- frameWidget(l)

This creates a new htmlwidget: 'widgetframe'.
Code: https://github.com/bhaskarvk/widgetframe/blob/master/R/widgetframe.R#L117

Scenario 2.1

w

This prints the widgetframe widget using the Method print.widgetframe which is almost similar to print.htmlwidget. In addition to generating the HTML for the 'widgetframe' widget, it also generates HTML for the enclosing widget (the leaflet widget in this case) under a sub directory called 'widget'. And finally displays the parent HTML using either Viewer or utils::browseURL

Code: https://github.com/bhaskarvk/widgetframe/blob/master/R/widgetframe.R#L146

Scenario 2.2

saveWidgetframe(w,'leaflet.html')

This will result in two files 'leaflet.html' which contains the Parent PymJS init code, and 'leaflet_widget/index.html' which contains the HTML code for the enclosed leaflet widget. Whether both these files are self-contained or not depends on the 'selfcontained' option passed to saveWidgetframe.
Things to note -

  • I did not want to shadow htmlwidgets::saveWidget so I named this one saveWidgetframe. (May be the saveWidget function needs to be a generic).
  • Even when you pass selfcontained=TRUE you don't get one self contained file, but two, the parent and the child. I purposefully made it this way, otherwise I'll have to embed the child inside the 'srcdoc' attribute of the parent's iframe element. I have some reservations about using the 'srcdoc' approach but I'm very easy to pursue with a convincing argument :).
  • The child's HTML lives inside a subdirectory tools::file_path_sans_ext(basename(file)),'_widget/index.html'), this makes it easy to separate the child's JS/CSS (in case of standalone=FALSE) from the parents. If standalone=TRUE I can easily change the code to generate the child HTML in the same directory as the parent as the JS/CSS are now inlined.

Scenario 3

Inside an R Markdown document

if you have frameWidget(l) inside a Rmd file, just like scenario 2.2, it will generate a separate HTML for the enclosed widget. This is again by design. You can try knitting the Rmd file inside the inst/examples folder to see it working.

Code: https://github.com/bhaskarvk/widgetframe/blob/master/R/knitr_support.R#L1


We could change this behavior of generating independent parent/child HTMLs to generating a single HTML with the child HTML content passed in the 'srcdoc' attribute of the iframe element. But the only real use case of widgetframes inside R markdowns is inside R Markdown sites and bookdown, because in those two cases the CSS of the site/book interferes with the widget's CSS. And in both these cases there is really no need for a standalone single HTML.
On the flip side the only disadvantage I see of not supporting a single HTML is that you can't upload it to Rpubs, which expects a standalone HTML.

Thoughts/Comments?

@bhaskarvk
Copy link
Author

I've made some progress and now generate the child widget HTMLs more predictably, and it works fairly well for single R markdown files. I need to test this thoroughly in bookdown and R Markdown websites. No shiny support for now, and I may never support it in Shiny unless there is a convincing use case.

@bhaskarvk
Copy link
Author

widgetframe is now on CRAN.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants