19

In my rmarkdown document, I am able to show and hide code with the following - which creates a convenient button on the righthand side of the document before each block of code:

output: 
  html_document:
    code_folding: hide

enter image description here enter image description here

Is there a similarly convenient method to hide tables or figures? If so, please provide a reference as I have not been able to find any. Otherwise a workaround would be appreciated, thank you!

iskandarblue
  • 7,208
  • 15
  • 60
  • 130
  • It is not results="hide" that you are intrested in? http://kbroman.org/knitr_knutshell/pages/Rmarkdown.html – Developer Mar 06 '17 at 16:11
  • 1
    Yes, but then there is no convenient way to "show" the results if you want to see them. `Results = "hide"` permanently hides them. I am interested in a button solution like the one above – iskandarblue Mar 06 '17 at 16:23

4 Answers4

27

I have not been able to get the above solution (or others I found) to work consistently, but using the in-line html (Bootstrap example/solution) I found at W3schools.com works well in Rmarkdown.

I use it to show a simple plot in html output in the example below. It should work with any chunk output:

<button class="btn btn-primary" data-toggle="collapse" data-target="#BlockName"> Show/Hide </button>  
<div id="BlockName" class="collapse">  

```{r}
plot(mtcars$disp, mtcars$mpg)
```

</div>

note: If you use this on multiple sections, each one needs a unique id (ie replace BlockName with a unique id for each section to be collapsed.)

Matt L.
  • 2,753
  • 13
  • 22
  • It is not clear which part of you example is used to hide the block and which is your code for session info. I assumed the button and the div components are what are needed but didn't have success. Is there anything in your r code block that is needed to make this work? – ansek Dec 24 '17 at 12:19
  • I edited it to the bare minimum so that it doesn't rely on any extra packages, above. see if that works. – Matt L. Dec 26 '17 at 04:54
  • 1
    if you want nicer `sessionInfo`, I recently found the functions in the `Hmisc` package to be helpful. Now I use: `Hmisc::markupSpecs$html$session()` – Matt L. Dec 26 '17 at 04:55
  • I also changed to include a plot- to be on topic with the original question, although this should work with any output, I think. – Matt L. Dec 26 '17 at 05:06
  • this is great. I can't seem to get a second toggle button to work on another chunk later in my document though. A second toggle button appears but when I click it, only the code for my first button opens, any ideas? – user63230 Jul 17 '18 at 15:27
  • to make more than one, make sure to change the name of subsequent div tags: eg `data-target="#BlockName2` and `id="BlockName2` – Matt L. Jul 18 '18 at 22:04
  • this also works for DT (which fails with the details tag) : https://stackoverflow.com/a/76977592/14208185 – StephGC Aug 25 '23 at 13:19
8

If you add this to the end of your .Rmd file

<script>
$( "input.hideshow" ).each( function ( index, button ) {
  button.value = 'Hide Output';
  $( button ).click( function () {
    var target = this.nextSibling ? this : this.parentNode;
    target = target.nextSibling.nextSibling.nextSibling.nextSibling;
    if ( target.style.display == 'block' || target.style.display == '' ) {
      target.style.display = 'none';
      this.value = 'Show Output';
    } else {
      target.style.display = 'block';
      this.value = 'Hide Output';
    }
  } );
} );
</script>

and then this before each chunk you want to have a toggle:

<input type=button class=hideshow></input>

(adapted from here: https://groups.google.com/forum/#!topic/knitr/d37E0mP3w6k)

Note: this will work if you show the code - if you are hiding the code (with echo = FALSE), change

target = target.nextSibling.nextSibling.nextSibling.nextSibling;

to

target = target.nextSibling.nextSibling;

Note 2: if you want to use the code_folding option, change

 target = target.nextSibling.nextSibling.nextSibling.nextSibling;

to

 target = target.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling;
Lucy
  • 981
  • 7
  • 15
  • Thanks, is there a reason it won't work with `code_folding`? – iskandarblue Mar 06 '17 at 20:11
  • It is a bit hacky, but I've updated so that it should work for `code_folding` - basically, adding the toggle adds another node that needs to be skipped over, so you need an additional `.nextSibling` in the script. – Lucy Mar 06 '17 at 21:00
  • 3
    This is great, thanks! Do you know how I could make it hidden by default, so that users can click a "Show output" button rather than coming across a massive table that needs to be hidden? Super useful feature, which I'd like to see added to KnitR etc. – lukeholman May 18 '17 at 06:12
  • @Lucy Do you know can I hide several consecutive images by clicking just one button? – Caterina Jan 04 '19 at 08:11
  • For the hidden by default behaviour that @lukeholman mentioned see the answer left by gclarkjr5, that worked for me – Ricky Jan 31 '21 at 04:42
3

I was able to get Lucy's code working for me, but I also think it's more useful and cleaner to have the outputs hidden by default. It's a very simple addition. Just execute jquery that clicks all the "Hide Output" buttons upon rendering. My code looks like this:

<script>
$( "input.hideshow" ).each( function ( index, button ) {
  button.value = 'Hide Output';
  $( button ).click( function () {
    var target = this.nextSibling ? this : this.parentNode;
    target = target.nextSibling.nextSibling;
    if ( target.style.display == 'block' || target.style.display == '' ) {
      target.style.display = 'none';
      this.value = 'Show Output';
    } else {
      target.style.display = 'block';
      this.value = 'Hide Output';
    }
  } );
} );

$("input.hideshow").click()
</script>

Only the last line before </script> was the addition.

gclarkjr5
  • 161
  • 1
  • 2
  • 10
0

Heyy so I changed the code of gclarkjr5 to have the table shown without being formatted. It will show the hidden button first and not modify the display of the table. So here goes:

Put this before the chunk you want to display:

<input type=button class=hideshow></input>

And then at the end of your markdown file:

<script>
$( "input.hideshow" ).each( function ( index, button ) {
  button.value = 'Show Output';
  $( button ).click( function () {
    var target = this.nextSibling ? this : this.parentNode;
    target = target.nextSibling.nextSibling;
    if ( target.style.display == 'none') {
      target.style.display = '';
      this.value = 'Hide Output';
    } else {
      target.style.display = 'none';
      this.value = 'Show Output';
    }
  } );
} );

$("input.hideshow").click()
</script>