rrpivottable

Make a radiobutton list for the stored rpivottable configuration name


The following is a link to a code that allows you to make several configuration savings, which you can load anytime as long as you don't clear your cookies.
I would like to know if it's possible to make a radiobutton, that displays a list of all the stored names.

The link: Make several configuration saves/loadings of rpivottable on R


Solution

  • Here's what I've got:

    You may want to adjust the size or position of the radio button container. It depends on how you use it. Right now the container will continue to grow (up to a point) as you add more content.

    This still uses the file or webpage name, so if you have more than one spreadsheet, you'll be able to save and keep the configurations separated.

    The YAML, options, CSS, libraries, and sample data.

    ---
    title: "testing rpivotTable cookie-ishness"
    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 {    /*Added other buttons*/
      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.15em;            /*Changed from 1.3em*/
        padding: .3em 0px;
        width: 20em;                 /*Changed from 18em*/
        text-decoration: none; /*no underline!!*/
        cursor: pointer;
    }
    .btn:active { /*simulate movement; added other buttons*/
      position: relative;
      top: 1px;
    }
    </style>
    
    ```{r data,include=F}
    # devtools::install_github("fraupflaume/rpivotTable")
    library(rpivotTable)
    library(tidyverse)
    data(mtcars)
    
    ```
    

    The buttons (not radio) and rpivotTable.

    ## 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>
    <a id='remoSaved' class='btn' style="background-color:black;color:white;">Remove Saved Configuration</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")) 
                ))
    ```
    

    The remaining code is Javascript. This creates the events, saves, retrieves, and deletes configurations, and creates the radio buttons.

    ```{r listenOrElse,results="asis",engine="js"}
    
    // for ONE TABLE
    setTimeout(function(){  // add to buttons
      radioStar();  // <= added in v3
      document.querySelector('a#saveNamed').addEventListener('click', savoring); 
      document.querySelector('a#restoNamed').addEventListener('click', giveItBack);
      document.querySelector('a#remoSaved').addEventListener('click', remIt);  // removing configs
      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!
        radBuilder(inName);  // <= added in v3; mod v4; add radio btn for new saved name
      };
      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
        retriever(confName);
      }
      function retriever(confName) {  // <= added in v3
        console.log("I'm listening! I swear!");
        el = document.querySelector('.rpivotTable');
        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);
            w2 = w.split("_").pop();   // remove file/page name <= changed in v3
            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);  // next step is a change in v3
          giveItBack(); // when unmatched name is chosen instead of re-prompting send them back
        }
        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!
      }
      function remIt(){
        el = document.querySelector('.rpivotTable');
        msg = "Identify the configuration for removal.";
        remName = prompt(msg, ['Enter a name with no spaces or special characters'])
        if(remName === null) {return;};                   // they changed their mind; nothing saved
        remName = remName.replace(/[^a-z0-9.]/gi, '');     // validate string
        path = window.location.pathname.split("/").pop().split(".").slice()[0]; //filename
        window.localStorage.removeItem(path + '_' + remName);
        rgetter = document.querySelector('#' + remName).parentNode;
        rgetter.remove();
      }
      function radioStar() { // create container *once*; size may have to be adjusted
        if(document.querySelector('#radIsland') == null) { // if an alert doesn't exist
            // one time = create island for radio buttons
          contLabel = document.createElement('div');
          contLabel.setAttribute(
            'style',
            'font-size: 1.2em; font-face: bold; color: #003b70; display: flex; flex-flow: wrap row;');
          contLabel.textContent = 'Choose from the available check points:';
          configCont = document.createElement('div');
          configCont.id = 'radIsland';
          configCont.setAttribute(
            'style',
            'border: 1px solid #003b70; min-width: 11em; width: auto; max-width: 55em; min-height: 10em; height: auto; border-radius: .5em; color: #003b70; display: flex; flex-flow: wrap row;'
          );
          pEl = document.querySelector('.rpivotTable').parentNode;
          pEl.prepend(configCont);        // but box above rpivottable
          pEl.prepend(contLabel);         // put the label on top
        }
        radCreation();
      }
      function radCreation(){
      // if island exists then move on
      // create radio buttons; when savoring runs, radio buttons need to be rebuilt/validated?
        var wk, rB, rLab, desc, newL, rCont, path, len;
        path = window.location.pathname.split("/").pop().split(".").slice()[0]; //filename
        len = window.localStorage.length
        for(i = 0; i < len; i++) {
          wk = window.localStorage.key(i);
          ind = wk.lastIndexOf('_');
          wkFile = wk.substr(0, ind);   // remove file/page name and table number
          chName = wk.split("_").pop();      // user chosen name
          if(wkFile === path) {              // only show radio if file names match
            radBuilder(chName);
          }
        }
      }
      function radBuilder(chName){
        console.log('building a button');
        rB = document.createElement('input');
        rB.type = 'radio';
        rB.name = 'rBtn';       // only one radio w/ same name can be selected at once
        rB.id = chName;         // id's have to be unique for rad groups
        rB.value = chName;
        rB.setAttribute(
            'style',
            'margin: 2px;');
        rB.addEventListener('click', function(){
          retriever(this.value)
        });
        rLab = document.createElement('label');
        rLab.htmlFor = chName;
        desc = document.createTextNode(chName);
        rLab.appendChild(desc);
        newL = document.createElement('br');
        fItem = document.createElement('div');
        fItem.setAttribute(
          'style',
          'width: 10em; height: 1.1em; margin: auto;');
        fItem.appendChild(rB);
        fItem.appendChild(rLab);
        fItem.appendChild(newL);
        rCont = document.getElementById('radIsland');
        rCont.appendChild(fItem);
      }
    }, 500);
    
    
    ```
    

    enter image description here enter image description here enter image description here enter image description here

    If you remove a configuration, the radio button goes away, as well.

    enter image description here enter image description here

    Saving a configuration will add a radio button for that configuration at that time

    enter image description here enter image description here

    You can add as many configurations as you would like.

    enter image description here

    Just select a new radio to change to a different configuration.

    enter image description here