Как добавить сворачивание кода для вывода фрагментов в html-документах rmarkdown
Я очень ценю функцию "code_folding" в RMarkdown. Однако мне действительно нужно, чтобы код отображался все время и переключал дисплей на выходе.
---
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
```
есть ли способ переключить вывод, а не код? Лучшее (но не идеальное) решение, о котором я думал, - это добавить collapse=TRUE
к кускам, но затем код и вывод по-прежнему отображаются одновременно.
ссылка на скомпилированный документ: http://rpubs.com/daynefiler/188408
3 ответов
TOC:
полный контроль над тем, какие блоки должны быть сложены
сложите все куски, содержащие более одной строки кода / вывода
1. Полный контроль над тем, какие куски должны быть сложены
Я хотел иметь ту же функциональность, а также и сделал следующее:
Я создал JavaScript, который выглядит как следует:
$(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');
});
});
поскольку я не JS crack, это может быть не идеально, но он делает то, что должен. Включите его в свой файл Rmd:
<script src="js/hideOutput.js"></script>
Я также написал некоторые определения CSS для стиля кнопки:
.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;
}
после включения обоих, JS-файла и таблицы стилей, вы можете скрыть куски, обернув вокруг них контейнер div одним из следующих классов:
скрыть выходной только
<div class="fold o">
```{r}
...
```
</div>
скрыть исходный код
<div class="fold s">
```{r}
...
```
</div>
скрыть
<div class="fold s o">
```{r}
...
```
</div>
скрипт определяет тип каждого фрагмента (например, исходный код, вывод текста или вывод графика) и помечает кнопки соответствующим образом.
результат выглядит так:
2. Сложите все куски, содержащие более одного строка кода / вывода
вот версия скрипта, которая добавляет функцию складывания ко всем кускам, которые длиннее одной строки:
$(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');
});
});
просто включите его с <script src="js/hideAll.js"></script>
и вам не нужно обертывать контейнеры div вокруг ваших фрагментов кода.
Одна вещь, которую вы должны добавить в свой документ Rmd, - это следующая глобальная опция chunk:
```{r, echo = F}
knitr::opts_chunk$set(out.extra = 'class="plot"')
```
это необходимо для идентификации графического вывода.
быстрый хакерский способ переключения раздела (не обязательно код):
заключите разделы для переключения с <div class="toggle"><button>TOGGLE_TEXT</button>
и <\div>
в свой .Файл 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>
положить на дно .Файл Rmd (или в идеале в a .JS файл, связанный со всеми вашими страницами).
<script>
$(".toggle").click(function() {
$(this).toggleClass("open");
});
</script>
положите это в свой .css-файл (вам придется играть с высотой для вашей кнопки).
.toggle {
height: 1.55em;
overflow-y: hidden;
}
.toggle.open {
height: auto;
}
Я прямо скопировал javascript из источника другого документа Rmarkdown, где я установил code_folding: show
. Я сохранил javascript как py_code_folding.js
и добавил <script src="py_code_folding.js"></script>
в верхней части моего документа Rmarkdown. Единственное ограничение заключается в том, что я должен был жестко закодировать в своем javascript, хочу ли я, чтобы блоки были изначально показаны или скрыты.
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");
});