How to add numbered section folding to rmarkdown - r

I am trying to show sections of text only after clicking on them (very much like code folding).
So far I am using the following html script at the beginning of my Rmd file:
<script language="javascript">
function toggle(num) {
var ele = document.getElementById("toggleText" + num);
var text = document.getElementById("displayText" + num);
if(ele.style.display == "block") {
ele.style.display = "none";
text.innerHTML = "show";
}
else {
ele.style.display = "block";
text.innerHTML = "hide";
}
}
</script>
But whenever I use it for sections/headers I lose the automatic numbering.
<a id="displayText" href="javascript:toggle(5);"><h1>I would like to code fold this section
</h1></a>
<div id="toggleText5" style="display: none">
Bla bla
</div>
And get a heading with numbering like this:
1 - I would like to code fold this section

Related

Set code hiding for specific code blocks in Rmarkdown [duplicate]

I really appreciate the "code_folding" feature in RMarkdown. However, what I really need is to have the code show all the time and toggle the display on the output.
---
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
```
Is there a way to toggle the output rather than the code? The best (but not ideal) solution I have thought of is to add collapse=TRUE to the chunks, but then the code and the output still display at the same time.
Link to the compiled document: http://rpubs.com/daynefiler/188408
TOC:
Full control over which chunks should be folded
Fold all chunks that contain more than one line of code/output
1. Full control over which chunks should be folded
I wanted to have the same functionality as well and did the following:
I created a JavaScript that looks as follows:
$(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');
});
});
Since I am no JS crack it might not be perfect, but it does what it is supposed to.
Include it in your Rmd file:
<script src="js/hideOutput.js"></script>
I also wrote some CSS definitions to style the button:
.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;
}
After including both, the JS file and the stylesheet, you can hide chunks by wrapping a div container around them with one of the following classes:
Hide output only
<div class="fold o">
```{r}
...
```
</div>
Hide source code
<div class="fold s">
```{r}
...
```
</div>
Hide both
<div class="fold s o">
```{r}
...
```
</div>
The script detects the type of each chunk (e.g. source code, text output or plot output) and labels the buttons accordingly.
The result looks like this:
2. Fold all chunks that contain more than one line of code/output
Here is a version of the script that adds the folding feature to all chunks that are longer than one line:
$(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');
});
});
Just include it with <script src="js/hideAll.js"></script> and you don't need to wrap div containers around your code chunks.
One thing you have to add in your Rmd document though is the following global chunk option:
```{r, echo = F}
knitr::opts_chunk$set(out.extra = 'class="plot"')
```
It is needed to identify graphical output.
How about this lo-fi solution?
<details><summary>Click here</summary>
Some text
```{r code}
# even code
print("Hello world!")
```
</details>
Not mine, but I like it.
A quick an hacky way to toggle a section (not necessarily code):
Enclose the sections to toggle with <div class="toggle"><button>TOGGLE_TEXT</button> and <\div> in your .Rmd file
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>
Put this at the bottom of the .Rmd file (or ideally in a .js file linked to all your pages).
<script>
$(".toggle").click(function() {
$(this).toggleClass("open");
});
</script>
Put this in your .css file (you'll have to play with the height for your button).
.toggle {
height: 1.55em;
overflow-y: hidden;
}
.toggle.open {
height: auto;
}
I straight up copied the javascript from the source of another Rmarkdown document where I set code_folding: show. I saved the javascript as py_code_folding.js and added <script src="py_code_folding.js"></script> to the top of my Rmarkdown document. The only limitation is that I had to hardcode in my javascript whether I want the blocks to be initially shown or hidden.
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");
});

How to add code folding to output chunks in rmarkdown html documents

I really appreciate the "code_folding" feature in RMarkdown. However, what I really need is to have the code show all the time and toggle the display on the output.
---
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
```
Is there a way to toggle the output rather than the code? The best (but not ideal) solution I have thought of is to add collapse=TRUE to the chunks, but then the code and the output still display at the same time.
Link to the compiled document: http://rpubs.com/daynefiler/188408
TOC:
Full control over which chunks should be folded
Fold all chunks that contain more than one line of code/output
1. Full control over which chunks should be folded
I wanted to have the same functionality as well and did the following:
I created a JavaScript that looks as follows:
$(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');
});
});
Since I am no JS crack it might not be perfect, but it does what it is supposed to.
Include it in your Rmd file:
<script src="js/hideOutput.js"></script>
I also wrote some CSS definitions to style the button:
.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;
}
After including both, the JS file and the stylesheet, you can hide chunks by wrapping a div container around them with one of the following classes:
Hide output only
<div class="fold o">
```{r}
...
```
</div>
Hide source code
<div class="fold s">
```{r}
...
```
</div>
Hide both
<div class="fold s o">
```{r}
...
```
</div>
The script detects the type of each chunk (e.g. source code, text output or plot output) and labels the buttons accordingly.
The result looks like this:
2. Fold all chunks that contain more than one line of code/output
Here is a version of the script that adds the folding feature to all chunks that are longer than one line:
$(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');
});
});
Just include it with <script src="js/hideAll.js"></script> and you don't need to wrap div containers around your code chunks.
One thing you have to add in your Rmd document though is the following global chunk option:
```{r, echo = F}
knitr::opts_chunk$set(out.extra = 'class="plot"')
```
It is needed to identify graphical output.
How about this lo-fi solution?
<details><summary>Click here</summary>
Some text
```{r code}
# even code
print("Hello world!")
```
</details>
Not mine, but I like it.
A quick an hacky way to toggle a section (not necessarily code):
Enclose the sections to toggle with <div class="toggle"><button>TOGGLE_TEXT</button> and <\div> in your .Rmd file
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>
Put this at the bottom of the .Rmd file (or ideally in a .js file linked to all your pages).
<script>
$(".toggle").click(function() {
$(this).toggleClass("open");
});
</script>
Put this in your .css file (you'll have to play with the height for your button).
.toggle {
height: 1.55em;
overflow-y: hidden;
}
.toggle.open {
height: auto;
}
I straight up copied the javascript from the source of another Rmarkdown document where I set code_folding: show. I saved the javascript as py_code_folding.js and added <script src="py_code_folding.js"></script> to the top of my Rmarkdown document. The only limitation is that I had to hardcode in my javascript whether I want the blocks to be initially shown or hidden.
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");
});

How to prevent unwanted line breaks before the table is printed

When button is clicked the control goes to the Javascript function print() and the table gets printed. But, it's showing almost 20 line breaks before the table gets printed and I want to prevent it.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var print=function()
{
document.write("<table border=5px>");
for(var i=1;i<1001;i++)
{
document.write("<tr>"+"<td>"+i+"</td>"+"</tr>"+"</br>");
}
document.write("</table>");
}
</script>
</head>
<body style="white-space: nowrap">
<input type="button" value="click here" onclick="print();" />
</body>
</html>
Remove closing <br> tag from your string:
var print=function()
{
document.write("<table border=5px>");
for(var i=1;i<1001;i++)
{
document.write("<tr>"+"<td>"+i+"</td>"+"</tr>"); // </br> removed here
}
document.write("</table>");
}
This is happening because you have a <br> tag in your for loop. If you want to have a linebreak between each table when you click your button that generates them you'll need to add the line break tag to the end of the closing table. (Or use CSS to create padding / margins)
var print=function() {
document.write("<table border=5px>");
for(var i=1;i<1001;i++) {
document.write("<tr>"+"<td>"+i+"</td>"+"</tr>"); }
document.write("</table> <br>"); }
Otherwise just remove it entirely.
var print=function() {
document.write("<table border=5px>");
for(var i=1;i<1001;i++) {
document.write("<tr>"+"<td>"+i+"</td>"+"</tr>"); }
document.write("</table>"); }

How to remove dash inside text with CSS?

In a page, I've got some text generated automatically like this:
Edward-Hopper-Grand-Palais
What I want is to remove the dash to remplace it by whitespace or a space with CSS.
Is that possible?
Thank for helping
http://jsfiddle.net/WYGu3/
Suppose you've a piece of markup such as this:
<p id="text"> Edward-Hopper-Grand-Palais </p>
Then the fastest way to perform a replace would be:
var str = document.getElementById("text").innerHTML;
str = str.replace(/-/g, ' ');
alert(str);
The /g here performs a global replace.
You cannot do such things with CSS. The hyphen characters do not constitute elements, so they cannot be referred to in CSS.
Very theoretically, you could create a font that has a space in place of hyphen and use that font via #font-face. But that would be awkward, and the hyphens would just look like spaces (e.g., copying content and pasting it as plain text would give you hyphens, not spaces).
So you need to modify the content server-side or client-side, as suggested in other answers.
I don't know how to do it with CSS, but with Javascript you can do this.
<script type="text/javascript">
function parseDisplay( result )
{
var displayedText = true;
for (var x = 0; x < result.length; x++)
{
var c = result.charAt(x);
if (c == '<')
{
displayedText = false;
}
else if (c == '>')
{
displayedText = true;
}
if (displayedText && c == '-')
{
result = result.substring(0,x) + ' ' + result.substring(x + 1, result.length);
}
}
return result;
}
</script>
If you are using this results for ID's or classes this function will leave everything inside of '< >' tags completely untouched! When you generate it just run it through this function before you display it!

How to expand nested HTML5 <details> elements to make a link target visible?

I have a html5 page which contains something like this:
<details>
<summary>X and Y</summary>
<details id="x">
<summary>X</summary>
Long text about x.
</details>
<details id="y">
<summary>Y</summary>
Long text about Y.
</details>
</details>
A lot of other stuff.
<a href="#x>Go to X</a>
<a href="#y>Go to Y</a>
I already use a CSS details:target spec to highlight the link target when a user clicks on one of the "Go to X/Y" links. However, if the top-level details-element is not expanded, the user can't see it and it seems like it wouldn't work.
So is there a way (preferably only html5 + css) to expand the top-level details-element when a link targeting some of its children is clicked?
The only way for now is using Javascript. You can read this for already written code: http://www.sitepoint.com/fixing-the-details-element/
I wrote this code
<script>
function openDetailsNested() {
var listOpen = document.querySelectorAll("details[open]");
if(listOpen.length > 0) {
for(var i=0; i<listOpen.length; i++) {
var elem = listOpen[i];
while (elem) {
if (elem.matches("DETAILS")) {
elem.setAttribute("open","");
}
elem = elem.parentElement;
}
}
}
}
window.addEventListener("load", openDetailsNested,true);
</script>

Resources