4

I am trying to add a button to an html file that I'm producing using RStudio and rmarkdown that copies a table produced with kableExtra to the clipboard.

As a demo, the following produces and displays a table:

library(dplyr)
library(kableExtra)

#making a dataframe into a table with kable


df<-data.frame(Flavor=c("Raspberry","Lemonade","Raspberry","Lemonade"),
           Color=c("Blue","Pink","Red","Yellow"))


table_out<-df%>%
  kable("html",align = 'clc')%>%
  kable_styling(full_width = F,position="left",bootstrap_options = c("striped","bordered"))%>%
  add_header_above(c("Colorful Stuff"=2))

table_out

I found that this code, borrowed from an answer here: https://stackoverflow.com/a/42210996/9731173, allows me to produce a button:

<script type="text/javascript">
function selectElementContents(el) {
    var body = document.body, range, sel;
    if (document.createRange && window.getSelection) {
        range = document.createRange();
        sel = window.getSelection();
        sel.removeAllRanges();
        try {
            range.selectNodeContents(el);
            sel.addRange(range);
        } catch (e) {
            range.selectNode(el);
            sel.addRange(range);
        }
        document.execCommand("copy");

    } else if (body.createTextRange) {
        range = body.createTextRange();
        range.moveToElementText(el);
        range.select();
        range.execCommand("Copy");
    }
}
<input type="button" value="Copy" onclick="selectElementContents( 
document.getElementById('table_out') );">

The issue with the above (so far as I can tell) is that I'm not referring to the table I produced with kableExtra correctly. When I click the Copy button in my rendered html file, it doesn't copy table_out to the clipboard.

How can I give my kableExtra table an Id and correctly refer to it so that the "Copy" button I made copies the table to the clipboard?

Edit: Here's what the rendered file looks like. I'm happy with the appearance, but hope to make the copy button functional:

enter image description here

Pake
  • 968
  • 9
  • 24
  • 2
    maybe this is helpful: https://stackoverflow.com/questions/21820888/knitr-wrapping-computer-output-in-html-tags – missuse Jun 04 '21 at 19:23

1 Answers1

2

I got this working by adding the id attribute to my kableExtra table, and then referencing the id in the copy button.

Looking at 10.1.11 here:https://bookdown.org/yihui/rmarkdown-cookbook/kable.html , you can use table.attr to add attributes.

You'll see that I changed the kableExtra part to include table.attr = "id=mytab", which allows for reference outside the chunk of R code

My functioning code in it's entirety is:

---
title: "Demo"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(dplyr)
library(kableExtra)
```



```{r}
#making a dataframe into a table with kable


df<-data.frame(Flavor=c("Raspberry","Lemonade","Rasp2berry","Lemonade"),
           Color=c("Blue","Pink","Red","Yellow"))


table_out<-df%>%
  kable("html",align = 'clc', table.attr = "id=mytab")%>%
  kable_styling(full_width = F,position="left",bootstrap_options = 
c("striped","bordered"))%>%
  add_header_above(c("Colorful Stuff"=2))

table_out

```





<script type="text/javascript">
function selectElementContents(el) {
    var body = document.body, range, sel;
    if (document.createRange && window.getSelection) {
        range = document.createRange();
        sel = window.getSelection();
        sel.removeAllRanges();
        try {
            range.selectNodeContents(el);
            sel.addRange(range);
        } catch (e) {
            range.selectNode(el);
            sel.addRange(range);
        }
        document.execCommand("copy");

    } else if (body.createTextRange) {
        range = body.createTextRange();
        range.moveToElementText(el);
        range.select();
        range.execCommand("Copy");
    }
}
<input type="button" value="Copy" onclick="selectElementContents( document.getElementById('mytab') );">

If you have a better solution, or stronger explanation, please still consider posting an answer. My solution is the result of brute force, not a wealth of knowledge.

Pake
  • 968
  • 9
  • 24