web-dev-qa-db-fra.com

Comment ajouter du pliage de code aux morceaux de sortie dans les documents HTML rmarkdown

J'apprécie vraiment la fonctionnalité "code_folding" de RMarkdown. Cependant, ce dont j'ai vraiment besoin, c'est que le code soit affiché en permanence et que l'affichage bascule sur l'affichage.

---
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
```

Y at-il un moyen de basculer la sortie plutôt que le code? La meilleure solution (mais pas idéale) à laquelle j'ai pensé consiste à ajouter collapse=TRUE aux fragments, mais le code et la sortie s'affichent toujours en même temps. 

Lien vers le document compilé: http://rpubs.com/daynefiler/188408

14
dayne

TOC:

  1. Contrôle total sur quels morceaux doivent être pliés

  2. Plier tous les morceaux contenant plus d'une ligne de code/sortie


1. Contrôle total sur quels morceaux doivent être pliés

Je voulais aussi avoir la même fonctionnalité et ai fait ce qui suit:

J'ai créé un JavaScript qui se présente comme suit:

$(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');
  });
});

Comme je ne suis pas un crack JS, il n’est peut-être pas parfait, mais il fait ce qu’il est supposé faire. Incluez-le dans votre fichier Rmd:

<script src="js/hideOutput.js"></script>

J'ai aussi écrit quelques définitions CSS pour styler le bouton:

.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;
}

Après avoir inclus les deux fichiers, le fichier JS et la feuille de style, vous pouvez masquer des morceaux en enveloppant un conteneur div autour d'eux avec l'une des classes suivantes:

Masquer la sortie uniquement

<div class="fold o">
```{r}
  ...
```
</div>

Masquer le code source

<div class="fold s">
```{r}
  ...
```
</div>

Masquer les deux

<div class="fold s o">
```{r}
  ...
```
</div>

Le script détecte le type de chaque bloc (par exemple, un code source, une sortie texte ou une sortie de tracé) et étiquette les boutons en conséquence.

Le résultat ressemble à ceci:

 enter image description here

 enter image description here


2. Pliez tous les morceaux contenant plus d’une ligne de code/sortie

Voici une version du script qui ajoute la fonction de pliage à tous les morceaux de plus d'une ligne:

$(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');
  });
});

Incluez-le simplement avec <script src="js/hideAll.js"></script> et vous n'aurez pas besoin d'encapsuler les conteneurs div autour de vos fragments de code . Une chose que vous devez ajouter dans votre document Rmd est l'option de fragment global suivante:

```{r, echo = F}
knitr::opts_chunk$set(out.extra = 'class="plot"')
```

Il est nécessaire d'identifier la sortie graphique.

30
Martin Schmelzer

Un moyen rapide et astucieux de changer de section (pas nécessairement de code):

Placez les sections à basculer avec <div class="toggle"><button>TOGGLE_TEXT</button> et <\div> dans votre fichier .Rmd

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>

Placez ceci au bas du fichier .Rmd (ou idéalement dans un fichier .js lié à toutes vos pages).

<script>
  $(".toggle").click(function() {
    $(this).toggleClass("open");
  });
</script>

Mettez ceci dans votre fichier .css (vous devrez jouer avec la hauteur de votre bouton).

.toggle {
  height: 1.55em;
  overflow-y: hidden;
}
.toggle.open {
  height: auto;
}
2
Lisa DeBruine

J'ai directement copié le javascript à partir de la source d'un autre document Rmarkdown où j'ai défini code_folding: show . J'ai enregistré le javascript en tant que py_code_folding.js et ajouté <script src="py_code_folding.js"></script> en haut de mon document Rmarkdown. La seule limitation est que je devais coder en dur dans mon javascript si je voulais que les blocs soient initialement affichés ou masqués.

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");
});
0
kdauria