The Code folding option in RMarkdown for html documents is awesome. That option makes the programmatic methodology transparent for those who are interested, without forcing the audience to scroll through miles of code. The tight placement of code with prose and interactive graphical output makes the whole project more accessible to a wider audience, and furthermore it reduces the need for additional documentation.
For a larger project, I'm using bookdown, and it works great. The only problem is that there is no code-folding option. Code folding is not currently enabled in bookdown. (see Enable code folding in bookdown )
I know I don't need an option to make it happen. I just need to paste the right code in the right place or places. But what code and where?
A viable alternative would be to put the code chunk below the chunk's outputs in the page. Or, finally, to put them as an appendix. I could do that with html but not reproducible like rbookdown.
Code or text folding, or less commonly holophrasting, is a feature of some graphical user interfaces that allows the user to selectively hide ("fold") or display ("unfold") parts of a document. This allows the user to manage large amounts of text while viewing only those subsections that are currently of interest.
Hide source code: ```{r, echo=FALSE} 1 + 1 ``` Hide text output (you can also use `results = FALSE`): ```{r, results='hide'} print("You will not see the text output.") ``` Hide messages: ```{r, message=FALSE} message("You will not see the message.") ``` Hide warning messages: ```{r, warning=FALSE} # this will generate ...
To use @Yihui's hint for a button that fold all code in the html output, you need to paste the following code in an external file (I named it header.html
here):
Edit: I modified function toggle_R
so that the button shows Hide Global
or Show Global
when clicking on it.
<script type="text/javascript"> // toggle visibility of R source blocks in R Markdown output function toggle_R() { var x = document.getElementsByClassName('r'); if (x.length == 0) return; function toggle_vis(o) { var d = o.style.display; o.style.display = (d == 'block' || d == '') ? 'none':'block'; } for (i = 0; i < x.length; i++) { var y = x[i]; if (y.tagName.toLowerCase() === 'pre') toggle_vis(y); } var elem = document.getElementById("myButton1"); if (elem.value === "Hide Global") elem.value = "Show Global"; else elem.value = "Hide Global"; } document.write('<input onclick="toggle_R();" type="button" value="Hide Global" id="myButton1" style="position: absolute; top: 10%; right: 2%; z-index: 200"></input>') </script>
In this script, you are able to modify the position and css code associated to the button directly with the style
options or add it in your css file. I had to set the z-index
at a high value to be sure it appears over other divisions.
Note that this javascript code only fold R code called with echo=TRUE
, which is attributed a class="r"
in the html. This is defined by command var x = document.getElementsByClassName('r');
Then, you call this file in the YAML header of your rmarkdown script, as in the example below:
--- title: "Toggle R code" author: "StatnMap" date: '`r format(Sys.time(), "%d %B, %Y")`' output: bookdown::html_document2: includes: in_header: header.html bookdown::gitbook: includes: in_header: header.html --- Stackoverflow question <https://stackoverflow.com/questions/45360998/code-folding-in-bookdown> ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` ## R Markdown This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>. When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: ```{r cars} summary(cars) ```
I finally found the solution !
While looking at the code folding behavior for normal html output (no bookdown), I was able to add it to bookdown. The main javascript function needs to find .sourceCode
class divisions to work with bookdown. However, this also requires complementary javascript functions of bootstrap, but not all. This works with gitbook
and html_document2
.
Here are the steps:
js
folder in the same directory than your Rmd filetransition.js
and collapse.js
here for instance: https://github.com/twbs/bootstrap/tree/v3.3.7/js and store them in your js
folderjs
folder called codefolding.js
with the following code. This is the same as for rmarkdown code_folding option but with pre.sourceCode
added to find R code chunks: codefolding.js
code:
window.initializeCodeFolding = function(show) { // handlers for show-all and hide all $("#rmd-show-all-code").click(function() { $('div.r-code-collapse').each(function() { $(this).collapse('show'); }); }); $("#rmd-hide-all-code").click(function() { $('div.r-code-collapse').each(function() { $(this).collapse('hide'); }); }); // index for unique code element ids var currentIndex = 1; // select all R code blocks var rCodeBlocks = $('pre.sourceCode, pre.r, pre.python, pre.bash, pre.sql, pre.cpp, pre.stan'); rCodeBlocks.each(function() { // create a collapsable div to wrap the code in var div = $('<div class="collapse r-code-collapse"></div>'); if (show) div.addClass('in'); var id = 'rcode-643E0F36' + currentIndex++; div.attr('id', id); $(this).before(div); $(this).detach().appendTo(div); // add a show code button right above var showCodeText = $('<span>' + (show ? 'Hide' : 'Code') + '</span>'); var showCodeButton = $('<button type="button" class="btn btn-default btn-xs code-folding-btn pull-right"></button>'); showCodeButton.append(showCodeText); showCodeButton .attr('data-toggle', 'collapse') .attr('data-target', '#' + id) .attr('aria-expanded', show) .attr('aria-controls', id); var buttonRow = $('<div class="row"></div>'); var buttonCol = $('<div class="col-md-12"></div>'); buttonCol.append(showCodeButton); buttonRow.append(buttonCol); div.before(buttonRow); // update state of button on show/hide div.on('hidden.bs.collapse', function () { showCodeText.text('Code'); }); div.on('show.bs.collapse', function () { showCodeText.text('Hide'); }); }); }
js
folder in not useful for the final document itself. When reading the js functions, I also added the option to show
code blocks by default, but you can choose to hide them with hide
.rmarkdown code:
--- title: "Toggle R code" author: "StatnMap" date: '`r format(Sys.time(), "%d %B, %Y")`' output: bookdown::html_document2: includes: in_header: header.html bookdown::gitbook: includes: in_header: header.html --- Stackoverflow question <https://stackoverflow.com/questions/45360998/code-folding-in-bookdown> ```{r setup, include=FALSE} # Add a common class name for every chunks knitr::opts_chunk$set( echo = TRUE) ``` ```{r htmlTemp3, echo=FALSE, eval=TRUE} codejs <- readr::read_lines("js/codefolding.js") collapsejs <- readr::read_lines("js/collapse.js") transitionjs <- readr::read_lines("js/transition.js") htmlhead <- paste(' <script>', paste(transitionjs, collapse = "\n"), '</script> <script>', paste(collapsejs, collapse = "\n"), '</script> <script>', paste(codejs, collapse = "\n"), '</script> <style type="text/css"> .code-folding-btn { margin-bottom: 4px; } .row { display: flex; } .collapse { display: none; } .in { display:block } </style> <script> $(document).ready(function () { window.initializeCodeFolding("show" === "show"); }); </script> ', sep = "\n") readr::write_lines(htmlhead, path = "header.html") ``` ## R Markdown This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>. When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: ```{r cars} summary(cars) ``` ```{r plot} plot(cars) ```
This script shows the buttons in the Rstudio browser but does not work well. However, this is ok with firefox.
You'll see that there is a little css
in this code, but of course you can modify the position and color and whatever you want on these buttons with some more css.
Edit 2017-11-13: Global code-folding button well integrated with individual bloc buttons. Function toggle_R
is finally not necessary, but you need to get function dropdown.js
in bootstrap.
Global button is called directly in the code chunk when calling js
files:
```{r htmlTemp3, echo=FALSE, eval=TRUE} codejs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/codefolding.js") collapsejs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/collapse.js") transitionjs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/transition.js") dropdownjs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/dropdown.js") htmlhead <- c( paste(' <script>', paste(transitionjs, collapse = "\n"), '</script> <script>', paste(collapsejs, collapse = "\n"), '</script> <script>', paste(codejs, collapse = "\n"), '</script> <script>', paste(dropdownjs, collapse = "\n"), '</script> <style type="text/css"> .code-folding-btn { margin-bottom: 4px; } .row { display: flex; } .collapse { display: none; } .in { display:block } .pull-right > .dropdown-menu { right: 0; left: auto; } .open > .dropdown-menu { display: block; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; -webkit-background-clip: padding-box; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0,0,0,.15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); box-shadow: 0 6px 12px rgba(0,0,0,.175); } </style> <script> $(document).ready(function () { window.initializeCodeFolding("show" === "show"); }); </script> ', sep = "\n"), paste0(' <script> document.write(\'<div class="btn-group pull-right" style="position: absolute; top: 20%; right: 2%; z-index: 200"><button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" data-_extension-text-contrast=""><span>Code</span> <span class="caret"></span></button><ul class="dropdown-menu" style="min-width: 50px;"><li><a id="rmd-show-all-code" href="#">Show All Code</a></li><li><a id="rmd-hide-all-code" href="#">Hide All Code</a></li></ul></div>\') </script> ') ) readr::write_lines(htmlhead, path = "/mnt/Data/autoentrepreneur/header.html") ```
The new global button shows a dropdown menu to choose between "show all code" or "hide all code". Using window.initializeCodeFolding("show" === "show")
all codes are shown by default, whereas using window.initializeCodeFolding("show" === "hide")
, all codes are hidden by default.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With