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");
});
Related
Is it possible to remove slide-number and footer elements from the title slide in Quarto?
---
title: "My prez"
format:
revealjs:
slide-number: c
footer: "Confidential"
---
Thanks!
You can do this using Revealjs API methods. So write the necessary Js code (To capture the event of slide being ready and slide changed and if the current slide is title slide, change the display of footer and slide number to none) in a html file and then attach that file to qmd file using include-after-body.
---
title: "My prez"
format:
revealjs:
slide-number: c
footer: "Confidential"
include-after-body: clean_title_page.html
---
## Slide A
## Slide B
clean_title_page.html
<style>
.hide {
display: none !important;
}
</style>
<script>
function remove() {
let footer = document.querySelector('div.footer');
let slideNo = document.querySelector('div.slide-number');
slideNo.classList.add('hide');
footer.classList.add('hide');
Reveal.on('slidechanged', event => {
if(Reveal.isFirstSlide()) {
slideNo.classList.add('hide');
footer.classList.add('hide');
} else {
slideNo.classList.remove('hide');
footer.classList.remove('hide');
}
});
}
window.onload = remove();
</script>
I would like to have a download button in the middle of a sentence to a pdf or csv document for example. This means there should be a small button in the sentence suggesting that you can download a document, not in a navigation or side bar. Here is some reproducible code:
---
title: "Download button in text Quarto"
format:
html:
code-fold: true
engine: knitr
---
I would like to have a download button [here]() for pdf or CSV document for example.
I am not sure if it is possible to implement a clean button in a sentence using downloadthis package because it should be in the middle of a sentence with text around.
Update
I have create quarto shortcode extension downloadthis that provides a shortcode to embed a download button more easily (in comparison to my old answer) and doesn't require to use an R package (but of course, this extension is inspired by {downloadthis})
So after installing that shortcode, we can use the shortcode as following,
---
title: "Download button in text Quarto"
format:
html:
css: style.css
engine: knitr
---
The following button is a download button for matcars data {{< downloadthis mtcars.csv
label="Download data" dname=mtcars id=mtcars-btn >}} You can download the mtcars data as csv file by clicking on it.
style.css
#mtcars-btn {
font-size: xx-small;
padding: 0.2rem 0.3rem !important;
}
#down-btn {
margin-right: 2px;
margin-left: 2px;
}
a:has(#mtcars-btn) {
text-decoration: none !important;
}
Explore here for more options and live demos.
Old Answer
Using a bit of CSS and javascript, it is possible to do very easily.
---
title: "Download button in text Quarto"
format:
html:
code-fold: true
include-after-body: add_button.html
engine: knitr
---
```{r}
#| echo: false
library(downloadthis)
mtcars %>%
download_this(
output_name = "mtcars dataset",
output_extension = ".csv",
button_label = "Download data",
button_type = "default",
self_contained = TRUE,
has_icon = TRUE,
icon = "fa fa-save",
id = "mtcars-btn"
)
```
The following button is a download button for matcars data <span id="down-btn"></span> You can download the mtcars data as csv file by clicking on it.
add_button.html
<style>
#mtcars-btn {
font-size: xx-small;
padding: 0.2rem 0.3rem !important;
}
#down-btn {
margin-right: 2px;
margin-left: 2px;
}
a:has(#mtcars-btn) {
text-decoration: none !important;
}
#mtcars-btn:focus,
#mtcars-btn:active {
box-shadow: none !important;
}
#mtcars-btn:hover {
transition: 0.2s;
filter: brightness(0.90);
}
#mtcars-btn:active {
filter: brightness(0.80);
}
</style>
<script>
function add_button() {
/* get the R generated button by its id */
let mtcars_btn = document.querySelector("a:has(#mtcars-btn)");
mtcars_btn.href = '#mtcars-btn';
/* get the placeholder where you want to put this button */
let down_btn = document.querySelector("span#down-btn");
/* append the R generated button to the placeholder*/
down_btn.appendChild(mtcars_btn)
}
window.onload = add_button();
</script>
Explanation
So what I have done here
At first, created a download button using the downloadthis with an id=mtcars-btn so that we can get hold of this generated button with js code using this #mtcars-btn id selector
Then created a placeholder inside the paragraph text using <span></span>, where I want the download button to be and also in this case, assigned an id down-btn to that span, so that we can target this span using #down-btn.
Then using js, simply appended that generated download button to placeholder span tag so that the button is in the place where we wanted it to be.
Lastly, used some css to make this button smaller, reduced button padding, created a bit left and right margin and removed the underline.
Thats it!
I am using the Divi Builder in WordPress to make a list of patents in the accordion format. However, I would like to format the accordion title (of each accordion element) so that on the left is the patent#, and on the right is the title of the patent.
To do this, I would like to know how I can split the title into 2 separate sections; 1 where I can put the title number, and the other where I can type the name of the patent. Sort of like this:
Another sketch to show what I want it to look like: sketch of the goal
Again I am using Divi Builder to do this as I am a novice using WordPress. But I am assuming I would have to write some custom CSS to format the title in this way in the Divi Builder.
First is it possible to do what I am trying to do?
If so how can I do this (in the Divi Builder environment)?
Unfortunately, not all of our requirements can be met by means of ready-made tools for building a website.
In such cases, we are forced to write "fixes" in such individual cases.
I offer you a js script that does the following:
Searches for titles with text that meets the following requirements:
Starts with #
After a hash without spaces, numbers
Example: #111
Wraps the found in the span with the class specified in the configuration (at the very top of the file)
I tested here
(function() {
// Config
let classFirstHeading = 'my-heading';
let headerSelector = '.et_pb_toggle_title'; // You can replace to your selector of heading
// end config;
var DOMReady = function(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
callback();
} else if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", callback);
} else if (document.attachEvent) {
document.attachEvent("onreadystatechange", function() {
if (document.readyState != "loading") {
callback();
}
});
}
}
function updateHeading() {
let headings = document.querySelectorAll(headerSelector);
headings.forEach(el => {
let textHeading = el.innerText;
let regexp = /^\#\d+/;
if(textHeading && regexp.test(textHeading.trim())) {
el.innerHTML = textHeading.replace(regexp, (match) => {
return '<span class="'+classFirstHeading+'">'+match+'</span> ';
});
}
});
}
window.updateHeading = updateHeading; // Give access from outside
DOMReady(() => {
updateHeading();
/* Test, you can remove this section */
let styleEl = document.createElement('style'); styleEl.type = 'text/css';
let css = `
.${classFirstHeading} {
display: inline-block;
font-size: 23px;
font-weight: 700;
margin-right: 15px;
padding: 10px 15px 10px 0;
border-right: 2px solid #000;
}
`;
styleEl.appendChild(document.createTextNode(css));
document.querySelector('head').appendChild(styleEl);
/*************************************/
});
})();
<h5 class="et_pb_toggle_title">#111 What is your refund policy?</h5>
If you don't know where to insert such code, install the Custom CSS and JS in Header & Footer plugin and just copy my js code to your page where you use the accordion
I am working on converting a tufte-LaTeX book to tufte-Bookdown using the tufte and msmbstyle packages. I have a whole bunch of sidenotes and would like the numbering to restart with each chapter so I don't reach like 400 by the end of the book.
I found this CSS code in the Bookdown GitHub for doing this with regular Bookdown, which uses footnotes/endnotes. However, my attempts to modify the code to work with sidenotes have failed. This is my current CSS addition, which just takes that code and drops in sidenote or sidenote-number (which Inspect Element suggests are the correct tags) where footnote originally was:
/* generate new footnote calls */
.sidenote-number::after {
content: counter(fn-call);
position: relative;
top: -.5em;
font-size: 85%;
line-height: 0;
vertical-align: baseline;
}
/* use a counter for footnotes numbering */
.sidenote ol {
list-style: none;
counter-reset: fn-number;
}
.sidenote li {
counter-increment: fn-number;
}
.sidenote li p:first-child::before {
content: counter(fn-number) '. ';
width: 1.5em;
float: left;
}
This does not work as intended, and instead adds a new counter that numbers each sidenote marker with a counter that resets for each marker, so the in-text marker gets a 1 and the sidenote marker gets a 2.
My CSS skills are not exceptional and I'm not sure of the right next step. How can I get the actual marker to reset?
You can see an example of a page built with tufte/msmbstyle here; sidenote 4 can be found by scrolling down just a bit.
I ended up paying someone to solve this. They wrote some JavaScript that will fix it. The following code can be saved as an HTML file, and added to the book with
includes:
in_header: thishtmlfile.html
in the YAML. Here is the code for the HTML/JS/Jquery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
$(document).ready(function () {
var element_label= $("label[for *= 'tufte-sn-']");
var count = $(element_label).length;
$(element_label).each(function( index ) {
//console.log( ++index + ": " + $( this ).text() );
$(this).attr('for','tufte-sn-'+ ++index);
$(this).text(index);
});
});
$(document).ready(function () {
var element_input= $("input[id *= 'tufte-sn-']");
var count = $(element_input).length;
$(element_input).each(function( index ) {
//console.log( ++index + ": " + $( this ).text() );
$(this).attr('id','tufte-sn-'+ ++index);
});
});
$(document).ready(function () {
var element_span= $("span[class *= 'sidenote-number']");
var count = $(element_span).length;
$(element_span).each(function( index ) {
//console.log( ++index + ": " + $( this ).text() );
$(this).text(++index);
});
});
</script>
My recommendation is that you fix it in Latex file first, and then import/Convert it.
At the beginning/preamble of the document add thse lines, it will to start/reset the sidenote counter at each chapter
% the answer --restarting the footnote at 0
\let\oldchapter\chapter
\def\chapter{%
\setcounter{footnote}{0}%
\oldchapter
}
% now your doc
\begin{document}
% would have helped if you pasted some chapters or your book...
% some chapters...
\chapter{First}
\yourtext
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");
});