Cómo agregar plegado de código a fragmentos de salida en documentos html rmarkdown
r-markdown (3)
Copié directamente el Javascript de la fuente de otro documento de Rmarkdown donde configuré
code_folding: show
.
py_code_folding.js
el javascript como
py_code_folding.js
y agregué
<script src="py_code_folding.js"></script>
en la parte superior de mi documento de Rmarkdown.
La única limitación es que tuve que codificar en mi javascript si quiero que los bloques se muestren u oculten inicialmente.
window.initializePythonCodeFolding = 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 = 10000;
// select all R code blocks
var rCodeBlocks = $(''pre.python'');
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'');
});
});
}
$(document).ready(function () {
window.initializePythonCodeFolding("show" === "show");
});
Realmente aprecio la función "code_folding" en RMarkdown. Sin embargo, lo que realmente necesito es que el código se muestre todo el tiempo y alternar la pantalla en la salida.
---
title: "test file"
author: "dayne"
date: "June 10, 2016"
output:
html_document:
code_folding: hide
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Here is a basic example.
```{r}
3 + 4
```
¿Hay alguna manera de alternar la salida en lugar del código?
La mejor (pero no ideal) solución en la que he pensado es agregar
collapse=TRUE
a los fragmentos, pero luego el código y la salida aún se muestran al mismo tiempo.
Enlace al documento compilado: http://rpubs.com/daynefiler/188408
Una forma rápida y hacky de alternar una sección (no necesariamente el código):
Adjunte las secciones para alternar con
<div class="toggle"><button>TOGGLE_TEXT</button>
y
</div>
en su archivo .Rmd
1. How many users are in the second, but not the first, user table?
<div class="toggle"><button>Solution</button>
```{r}
setdiff(user2, user) %>% nrow()
```
</div>
Ponga esto en la parte inferior del archivo .Rmd (o idealmente en un archivo .js vinculado a todas sus páginas).
<script>
$(".toggle").click(function() {
$(this).toggleClass("open");
});
</script>
Pon esto en tu archivo .css (tendrás que jugar con la altura de tu botón).
.toggle {
height: 1.55em;
overflow-y: hidden;
}
.toggle.open {
height: auto;
}
TOC:
-
Control total sobre qué trozos deben plegarse
-
Dobla todos los fragmentos que contienen más de una línea de código / salida
1. Control total sobre qué trozos deben plegarse
También quería tener la misma funcionalidad e hice lo siguiente:
Creé un JavaScript que se ve de la siguiente manera:
$(document).ready(function() {
$chunks = $(''.fold'');
$chunks.each(function () {
// add button to source code chunks
if ( $(this).hasClass(''s'') ) {
$(''pre.r'', this).prepend("<div class=/"showopt/">Show Source</div><br style=/"line-height:22px;/"/>");
$(''pre.r'', this).children(''code'').attr(''class'', ''folded'');
}
// add button to output chunks
if ( $(this).hasClass(''o'') ) {
$(''pre:not(.r)'', this).has(''code'').prepend("<div class=/"showopt/">Show Output</div><br style=/"line-height:22px;/"/>");
$(''pre:not(.r)'', this).children(''code:not(r)'').addClass(''folded'');
// add button to plots
$(this).find(''img'').wrap(''<pre class=/"plot/"></pre>'');
$(''pre.plot'', this).prepend("<div class=/"showopt/">Show Plot</div><br style=/"line-height:22px;/"/>");
$(''pre.plot'', this).children(''img'').addClass(''folded'');
}
});
// hide all chunks when document is loaded
$(''.folded'').css(''display'', ''none'')
// function to toggle the visibility
$(''.showopt'').click(function() {
var label = $(this).html();
if (label.indexOf("Show") >= 0) {
$(this).html(label.replace("Show", "Hide"));
} else {
$(this).html(label.replace("Hide", "Show"));
}
$(this).siblings(''code, img'').slideToggle(''fast'', ''swing'');
});
});
Como no soy un crack de JS, puede que no sea perfecto, pero hace lo que se supone que debe hacer. Inclúyalo en su archivo Rmd:
<script src="js/hideOutput.js"></script>
También escribí algunas definiciones CSS para diseñar el botón:
.showopt {
background-color: #004c93;
color: #FFFFFF;
width: 100px;
height: 20px;
text-align: center;
vertical-align: middle !important;
float: right;
font-family: sans-serif;
border-radius: 8px;
}
.showopt:hover {
background-color: #dfe4f2;
color: #004c93;
}
pre.plot {
background-color: white !important;
}
Después de incluir ambos, el archivo JS y la hoja de estilo, puede ocultar fragmentos envolviendo un contenedor div a su alrededor con una de las siguientes clases:
Ocultar solo salida
<div class="fold o">
```{r}
...
```
</div>
Ocultar código fuente
<div class="fold s">
```{r}
...
```
</div>
Ocultar ambos
<div class="fold s o">
```{r}
...
```
</div>
El script detecta el tipo de cada fragmento (por ejemplo, código fuente, salida de texto o salida de trazado) y etiqueta los botones en consecuencia.
El resultado se ve así:
2. Doble todos los fragmentos que contengan más de una línea de código / salida
Aquí hay una versión del script que agrega la función de plegado a todos los fragmentos que son más largos que una línea:
$(document).ready(function() {
$plots = $(''img.plot'');
$chunks = $(''pre'').has(''code'');
$chunks = $chunks.filter(function(idx) {
return $(this).children(''code'').outerHeight(false) > parseInt($(this).css(''line-height''));
});
$chunks.each(function () {
if($(this).hasClass(''r'')) {
$(this).append("<div class=/"showopt/">Show Source</div><br style=/"line-height:22px;/"/>");
} else {
$(this).append("<div class=/"showopt/">Show Output</div><br style=/"line-height:22px;/"/>");
}
});
$plots.each(function () {
$(this).wrap(''<pre class=/"plot/"></pre>'');
$(this).parent(''pre.plot'').prepend("<div class=/"showopt/">Show Plot</div><br style=/"line-height:22px;/"/>");
});
// hide all chunks when document is loaded
$chunks.children(''code'').toggle();
$(''pre.plot'').children(''img'').toggle();
// function to toggle the visibility
$(''.showopt'').click(function() {
var label = $(this).html();
if (label.indexOf("Show") >= 0) {
$(this).html(label.replace("Show", "Hide"));
} else {
$(this).html(label.replace("Hide", "Show"));
}
$(this).siblings(''code, img'').slideToggle(''fast'', ''swing'');
});
});
Simplemente
<script src="js/hideAll.js"></script>
con
<script src="js/hideAll.js"></script>
y no necesita envolver contenedores div alrededor de sus fragmentos de código.
Sin embargo, una cosa que debe agregar en su documento Rmd es la siguiente opción de fragmento global:
```{r, echo = F}
knitr::opts_chunk$set(out.extra = ''class="plot"'')
```
Es necesario para identificar la salida gráfica.