The following code I found on an other post (I could link if anybody is interested) adds the saving option on the R rpivottable using flexdashboard. The saving is done through cookies.
I am trying to recreate it but having multiple saving options, basically have SAVE1, SAVE2,.. and being able to load the wanted save. I am unexperienced with JS so it is really hard to do anything.
---
title: "rpivottable_test"
output: html_document
---
knitr::opts_chunk$set(echo = FALSE)
# devtools::install_github("fraupflaume/rpivotTable")
library(rpivotTable)
data(mtcars)
names(mtcars)[10] <- "George.Dontas"
Save Current Configuration Restore Previous Configuration
rpivotTable(mtcars,rows="George.Dontas", cols = c("cyl"), width = "90%", height = "40%",
rendererOptions = list(
c3 = list(legend = list(show = FALSE),
data = list(labels = TRUE),
options = list(responsive = TRUE,
maintainAspectRatio = FALSE),
size = list(width = "600",
height = "500")),
d3 = list(size = list(width = "500", height = "500"))))
// save current state of the tables to my browser
setTimeout(function(){ //add the events first
document.querySelector('a#saveBtn').addEventListener('click', savoring);
document.querySelector('a#restoBtn').addEventListener('click', giveItBack);
function savoring() { // function to save
el = document.querySelectorAll('.rpivotTable');
for(i=0; i < el.length; i++){
elId = el[i].getAttribute("id");
stringy = $('#' + elId).data("pivotUIOptions"); // collect rows/columns filters
delete stringy['aggregators']; // remove the arbitrary
delete stringy['renderers'];
stringy2 = JSON.stringify(stringy); // make it one key:value
window.localStorage.setItem('table' + i, stringy2); // store it!
}
};
function giveItBack() { // function to regurgitate
el = document.querySelectorAll('.rpivotTable');
console.log("working on the giver");
ods = [...el[0].ownerDocument.scripts]; // make it an array
for(j=0; j < el.length; j++){
elId = el[j].getAttribute("id");
where = ods.filter(function(ods){ // filter scripts for table data
return ods.dataset['for'] === elId;
})[0].innerHTML;
where2 = JSON.parse(where).x.data; // WOOO HOO! I figured it out!!
where3 = HTMLWidgets.dataframeToD3(where2); // finally sheesh!!
gimme = window.localStorage.getItem('table' + j); // get storage
$('#' + elId).pivotUI(where3, JSON.parse(gimme), true, "en"); // put it back!
}
}
},100);
This uses the default system alert and prompt boxes. These vary in appearance a bit from one OS to another.
I've included CSS for the buttons and RMD. I used html_document
. If you use flex_dashboard
you won't need the CSS for the class main-container
. The CSS for body
may or may not be useful (depending on what else you have going on).
If you're using the Cran package, the rendererOptions
won't work as-is. You have to remove a list level after you make the object. The D3 rendererOptions won't work unless you change the Javascript file, d3_renderers.js, in the rpivotTable
package. (That's what I did with my fork.) If you use my fork, it will work as-is.
I've added handlers for
You may notice quite a few changes in the restoration function. That's because the original code would lost subtotals
, sorters
, and the renderer
tsv
.
I tried to think of anything that could go wrong and this is where I'm at. If you run into any issues, let me know. If you have questions, ask.
The YAML, options, and CSS:
---
title: "button and input tester!"
author: "me"
date: '2022-05-12'
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
<style>
body { /*push content away from far right and left edges*/
margin-right: 2%;
margin-left: 2%;
}
.main-container {
max-width: unset;
}
.btn {
vertical-align: middle;
-moz-box-shadow: 0px 10px 14px -7px #000000;
-webkit-box-shadow: 0px 10px 14px -7px #000000;
box-shadow: 0px 10px 14px -7px #000000;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
border: .5px solid black;
display: inline-block;
font-size: 1.2em;
padding: .3em 0px;
width: 20em;
text-decoration: none; /*no underline!!*/
cursor: pointer;
}
.btn:active { /*simulate movement*/
position: relative;
top: 1px;
}
</style>
The table.
```{r data,include=F}
# devtools::install_github("fraupflaume/rpivotTable")
library(rpivotTable)
data(mtcars)
```
## Make it Interesting...or not
Do you want to save or restore the previously saved pivot tables' configuration?
<a id='saveNamed' class='btn' style="background-color:#003b70;color:white;">Save Configuration by Name</a>
<a id='restoNamed' class='btn' style="background-color:#b21e29;color:white;">Restore Configuration with Custom Name</a>
```{r showMe, echo=FALSE, fig.show="hold"}
rpivotTable(mtcars, rows="am", cols = c("cyl"), width = "90%",
height = "40%", subtotals = TRUE,
rendererOptions = list(
c3 = list(legend = list(show = FALSE),
data = list(labels = TRUE),
options = list(responsive = TRUE,
maintainAspectRatio = FALSE),
size = list(width = "600",
height = "500")),
d3 = list(size = list(width = "500", height = "500"))
))
```
That's all, folks.
Lastly, the JS.
```{r listenOrElse,results="asis",engine="js"}
// for ONE TABLE
setTimeout(function(){ // add to buttons
document.querySelector('a#saveNamed').addEventListener('click', savoring);
document.querySelector('a#restoNamed').addEventListener('click', giveItBack);
function savoring() { // function to save
el = document.querySelector('.rpivotTable');
msg = "Choose a name for the configuration that you are saving.";
inName = prompt(msg, ['Enter a name with no spaces or special characters'])
if(inName === null) {return;}; // they changed their mind; nothing saved
inName = inName.replace(/[^a-z0-9.]/gi, ''); // validate string
path = window.location.pathname.split("/").pop().split(".").slice()[0]; //filename
elId = el.getAttribute("id");
stringy = $('#' + elId).data("pivotUIOptions"); // collect rows/col filters
delete stringy['aggregators']; // remove not-parse-friendly keys
delete stringy['renderers'];
stringy2 = JSON.stringify(stringy); // one key:value pair for storage
window.localStorage.setItem(path + '_' + inName, stringy2); // STORE it!
};
function giveItBack() { // function to regurgitate
el = document.querySelector('.rpivotTable');
msg = "Enter the name of the configuration you would like to retrieve.";
confName = prompt(msg, ["Enter a name with no spaces or special characters"]);
if(confName === null) {return;};
confName = confName.replace(/[^a-z0-9.]/gi, ''); // validate string
ods = [...el.ownerDocument.scripts]; // make it an array
path = window.location.pathname.split("/").pop().split(".").slice()[0]; //filename
elId = el.getAttribute("id");
where = ods.filter(function(ods){ // filter scripts for data
return ods.dataset['for'] === elId;
})[0].innerHTML;
where2 = JSON.parse(where).x.data; // format data for pivotUI()
where3 = HTMLWidgets.dataframeToD3(where2); // ...still formatting
if(window.localStorage.getItem(path + '_' + confName) === null) { // alert
len = window.localStorage.length
var str;
for(i = 0; i < len; i++) {
w = window.localStorage.key(i);
ind = w.lastIndexOf('_');
w2 = w.substr(ind + 1); // remove file/page name and table number
str = str + w2 + '\n'; // make one long string of names
}
str2 = "WARNING: There is no saved pivot table configuration with the name " + confName + '.';
str2 += " Here is a list of the configuration names that are currently stored for this page:\n";
str2 += str;
alert(str2);
confName = prompt(msg, ["Enter a name with no spaces or special characters"]);
if(confName === null) {
return
};
confName = confName.replace(/[^a-z0-9.]/gi, ''); // validate string
}
gimme = window.localStorage.getItem(path + '_' + confName); // get storage
gimmeMore = JSON.parse(gimme); // prepare for recall
if(where.includes('"subtotals":true')){ // is the option 'subtotal' used?
gimmeMore.renderers = $.pivotUtilities.subtotal_renderers;
gimmeMore.dataClass = $.pivotUtilities.SubtotalPivotData;
};
if(where.includes('"tsv":true')){ // is the option 'tsv' used?
gimmeMore.renderers = $.extend(gimmeMore.renderers, $.pivotUtilities.export_renderers);
};
if(where.includes('sortAs')){
// passed as a function, they will get lost in save & retrieve
stringy = $('#' + elId).data("pivotUIOptions").sorters;
gimmeMore.sorters = stringy;
}
$('#' + elId).pivotUI(where3, gimmeMore, true, "en"); // put it back!
};
}, 500);
```